Problem mit for Schleife

Wie rufe ich R-Funktionen auf, wie selektiere ich Daten, ich weiß nicht genau ....

Moderatoren: EDi, jogo

Antworten
Koplino

Problem mit for Schleife

Beitrag von Koplino »

Hallo,
habe problem mit einer for-Schleife:
Ich habe eine Stichprobe mit Zurücklegen aus den 12 Monaten des Jahres. Ich will jetzt wissen, wie oft bei meiner Stichprobe zwei gleiche Monate gezogen werden, wenn ich 6 mal ziehe. Dazu simuliere ich die Stichprobe sehr oft und zähle die Male, wo ein Monat zwei mal oder öfter gezogen wird.
So die Idee. Wenn ich mir aber eine Funktion schreibe, die mir die Anzahl der Treffer (= der Anzahl der Ziehungen, bei der ein Monat zwei mal oder öfter gezogen wird), bekomme ich 1 zurück, auch wenn ich bei dem data.frame mehr als 1 sehen kann. Wieso ? Hier der Code:

Code: Alles auswählen

z<-c("jan","feb","mar","apr","mai","juni","juli","aug","sept","okt","nov","dez")
sample(z,6,replace = TRUE,prob = c(0.077,0.077,0.077,0.077,0.077,
                                   0.077,0.10,0.10,0.10,0.077,0.077,0.077))

geb<- replicate(50, sample(z,6,replace = TRUE,prob = c(0.077,0.077,0.077,0.077,0.077,0.077,0.10,0.10,0.10,0.077,0.077,0.077)))

#Habe einen Wahrscheinlichkeitsvektor, da nicht alle Monate gleich wahrscheinlich sind.

anztreffer <- function(a){
  treffer=0
  for(i in 1:50){
   if(max(table(a[,i]))>=2){
     treffer=treffer + 1
  }
return(treffer)}}
Was stimmt hier nicht? Danke im Voraus.
jogo
Beiträge: 2085
Registriert: Fr Okt 07, 2016 8:25 am

Re: Problem mit for Schleife

Beitrag von jogo »

Hallo Koplino,

willkommen im Forum!
Es ist immer etwas schwierig, sich in fremde Quelltexte einzuarbeiten, wenn diese unkommentiert sind.
Meistens ist für jemanden, der gleiches programmieren möchte ein komplettes Neuprogrammieren wesentlich einfacher.
Etwas stutzig machten mich die Wahrscheinlichkeiten für die Monate; diese entsprechen nicht dem üblichen Auftreten:

Code: Alles auswählen

#> c(31, 28, 31,  30, 31, 30,  31, 31, 30,  31, 30, 31)/365
# [1] 0.08493151 0.07671233 0.08493151 0.08219178 0.08493151 0.08219178 0.08493151 0.08493151
# [9] 0.08219178 0.08493151 0.08219178 0.08493151
Die von Dir angegebenen Wahrscheinlichkeiten ergeben in der Summe weniger als 100%

Code: Alles auswählen

#> sum(c(0.077,0.077,0.077,0.077,0.077,0.077,0.10,0.10,0.10,0.077,0.077,0.077))
#[1] 0.993
Welche Bewandnis hat es damit?

Die Verwendung von replicate() ist gut. Allerdings würde ich bei der Testroutine eine schreiben, die eine einzelne Ziehung testet und dabei TRUE oder FALSE zurückliefert. Um die Gesamtheit der Ziehungen die Auswertung durchzuführen, kann man apply() über die Datenmatrix jagen.

Hier schon mal das Kernstück der Programmierung:

Code: Alles auswählen

z <- c("jan","feb","mar","apr","mai","juni","juli","aug","sept","okt","nov","dez")
s <- sample(z, 6, replace=TRUE, prob=c(31, 28, 31,  30, 31, 30,  31, 31, 30,  31, 30, 31)/365)
any(table(s)>1) ### Auswertung für ein sample
So, jetzt habe ich Deinen Code analysiert:
soweit sieht er nicht schlecht aus - nur ein kleiner Fehler mit großer Wirkung:
das return(...) steht etwas zu früh. Es muss als letztes stehen vor der geschweiften Klammer, die die Funktionsdefinition abschließt.
Also:

Code: Alles auswählen

anztreffer <- function(a){
  treffer=0
  for(i in 1:50) {
    if(max(table(a[,i]))>=2){
      treffer=treffer + 1
    }
  }
  return(treffer)
}

anztreffer(geb)
Noch eine Anmerkung zu der Art des Programmierens:
Es ist besser, wenn die Funktion die Datenmenge nicht kennen muss. Stell Dir vor Du möchtest nicht nur 50 Ziehungen durchführen sondern 500. Du müsstest bei Deiner Variante nicht nur bei der Generation der Daten die Anzahl ändern sondern Du müsstest in Deiner Funktion die for-Schleife ändern: for (i in 1:500)
Hier wäre for (i in 1:ncol(a)) besser (weil robuster).

Meine Variante sieht inzwischen so aus:

Code: Alles auswählen

z <- c("jan","feb","mar","apr","mai","juni","juli","aug","sept","okt","nov","dez")

testSample <- function() {
  s <- sample(z, 6, replace=TRUE, prob=c(31, 28, 31,  30, 31, 30,  31, 31, 30,  31, 30, 31)/365)
  any(table(s)>1) ### Auswertung für ein sample
}
sum(replicate(50, testSample()))
Gruß, Jörg
Antworten