Dppelschleife

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

Moderatoren: EDi, jogo

Paul_CU

Dppelschleife

Beitrag von Paul_CU »

Hallo,

ich wuerde gern die folgende for-Schleife hier in eine andere Schleife einbetten:

Code: Alles auswählen

ext.var <- 614:623
x3<-matrix(data=NA, nrow=max(ext.var), ncol=5)
for(i in ext.var){
  x3[i,1] <- sd(dfcr[,i][dfcr[,81] == 5], na.rm = T) 
  x3[i,2] <- sd(dfcr[,i][dfcr[,81] == 10], na.rm = T) 
  x3[i,3] <- as.numeric(leveneTest(dfcr[,i] ~ factor(dfcr$lr))[[1]][2]) # df2
  x3[i,4] <- as.numeric(leveneTest(dfcr[,i] ~ factor(dfcr$lr))[[2]][1]) # F-value
  x3[i,5] <- as.numeric(leveneTest(dfcr[,i] ~ factor(dfcr$lr))[[3]][1]) # p-value
}
x3[ext.var,]
Der Faktor, der die andere Schleife durchlaufen soll, geht von 1:21. (Da das etwas umstaendlich aussieht, habe ich auch versucht, obige Schleife mit lapply oder apply zu erhalten, bin allerdings gescheitert.)
Die andere Schleife koennte in etwa so aussehen, allerdings bin ich nicht weitergekommen:

Code: Alles auswählen

ev <- 1:21
# Hier fehlt etwas?
for(j in ev) {
ext.var <- 614:623
x3<-matrix(data=NA, nrow=max(ext.var), ncol=5)
for(i in ext.var){
  x3[i,1] <- sd(dfcr[,i][dfcr[,81] == 5][df[,625]==j], na.rm = T) 
  x3[i,2] <- sd(dfcr[,i][dfcr[,81] == 10][df[,625]==j], na.rm = T) 
  x3[i,3] <- as.numeric(leveneTest(dfcr[,i][df[,625]==j] ~ factor(dfcr$lr[df[,625]==j]))[[1]][2]) # df2
  x3[i,4] <- as.numeric(leveneTest(dfcr[,i][df[,625]==j] ~ factor(dfcr$lr[df[,625]==j]))[[2]][1]) # F-value
  x3[i,5] <- as.numeric(leveneTest(dfcr[,i][df[,625]==j] ~ factor(dfcr$lr[df[,625]==j]))[[3]][1]) # p-value
}
x3[ext.var,]
# Hier fehlt auch was?
}
Insgesamt sind es also 210 leveneTests, die durchgefuehrt werden sollen.

Fuer Vorschlaege bin ich dankbar!
Paul
bigben
Beiträge: 2771
Registriert: Mi Okt 12, 2016 9:09 am

Re: Dppelschleife

Beitrag von bigben »

Hi!
Woraus leitest Du ab, dass an den gekennzeichneten Stellen etwas fehlt? Du erzeugst halt 21mal eine Matrix x3 - die Ergebnisse wirst Du noch zwischenspeichern müssen.

LG,
Bernhard
---
Programmiere stets so, dass die Maxime Deines Programmierstils Grundlage allgemeiner Gesetzgebung sein könnte
Paul_CU

Re: Dppelschleife

Beitrag von Paul_CU »

Danke fuer die Antwort. An der ersten Stelle scheint nichts zu fehlen, an der zweiten wie die Ergebnisse zwischengespeichert werden koennen. Da stehe ich auf dem Schlauch, denn das scheint notwendig zu sein, da, wenn ich den Code so wie er ist durchlaufen lasse, diese Fehlermeldung kommt:

Code: Alles auswählen

 Error in `contrasts<-`(`*tmp*`, value = contr.funs[1 + isOF[nn]]) : 
  contrasts can be applied only to factors with 2 or more levels 
bigben
Beiträge: 2771
Registriert: Mi Okt 12, 2016 9:09 am

Re: Dppelschleife

Beitrag von bigben »

Paul_CU hat geschrieben: Sa Mai 27, 2017 2:02 amda, wenn ich den Code so wie er ist durchlaufen lasse, diese Fehlermeldung kommt
Der Code, der da oben steht, oder weiterer Code, den Du uns bislang nicht gezeigt hast, und zu dem wir also nichts sagen können?
Code, den Du selbst geschrieben und verstanden hast, oder fremden Code, von dem wir nicht genau wissen, wie er läuft?
Sollen wir raten, wie die Ergebnisse der Schleifen nachher vorliegen sollen, oder gibt es dafür Vorgaben?

LG,
Bernhard
---
Programmiere stets so, dass die Maxime Deines Programmierstils Grundlage allgemeiner Gesetzgebung sein könnte
Paul_CU

Re: Dppelschleife

Beitrag von Paul_CU »

Tut mir Leid, dass es unklar war. Ich habe den zweiten Code vom OP durchlaufen lassen und dann die oben genannte Fehlermeldung erhalten.
Am Ende soll eine 210x5 Matrix herauskommen, also x3 21 mal hintereinander. Das ist alles. Es fehlt vermutlich nur eine Zeile Code, die das bewerkstelligt, hinter

Code: Alles auswählen

x3[ext.var,]
?

Cheers,
Paul
jogo
Beiträge: 2085
Registriert: Fr Okt 07, 2016 8:25 am

Re: Dppelschleife

Beitrag von jogo »

Hallo Paul,

willkommen im Forum!
Paul_CU hat geschrieben: Fr Mai 26, 2017 9:35 pm ich wuerde gern die folgende for-Schleife hier in eine andere Schleife einbetten:

Code: Alles auswählen

ext.var <- 614:623
..
Diese Schleife würde ich so erledigen:

Code: Alles auswählen

my.stat <- function(x) c(
  sd05= sd(x[dfcr[,81] ==  5], na.rm = TRUE), 
  sd10= sd(x[dfcr[,81] == 10], na.rm = TRUE), 
  df2 = as.numeric(leveneTest(x ~ factor(dfcr$lr))[[1]][2]), # df2
  F= as.numeric(leveneTest(x ~ factor(dfcr$lr))[[2]][1]),    # F-value
  p= as.numeric(leveneTest(x ~ factor(dfcr$lr))[[3]][1])     # p-value
)

ext.var <- 614:623
x3 <- sapply(dfcr[ext.var], my.stat)
# colnames(x3) <- ext.var  # eventuell noch Namen setzen. Variante:
# colnames(x3) <- names(dfcr)[ext.var]
Aus welchem Paket stammt eigentlich die Funktion leveneTest ?
Und die Werte, die Du aus dem Ergebnis dieser Funktion abgreifst sind wirklich nich numerisch, so dass Du sie explizit umwandeln musst mit as.numeric() :?:

Deine Doppelschleife durchschaue ich nicht. Insbesondere die Konstruktion:

Code: Alles auswählen

sd(dfcr[,i][dfcr[,81] == 5][df[,625]==j], na.rm = T)
kann ich mir ohne gegebene Daten nicht vorstellen. Wie kannst Du Dir bei der zweiten Selektion [df[,625]==j] noch sicher sein, dass der Index noch zum Ergebnis der ersten Selektion dfcr[,i][dfcr[,81] == 5] passt?

Kannst Du bitte mal erläutern, welche Verbindung zwischen den Dataframes dfcr und df besteht? Haben beide die gleich Zeilenanzahl? Beinhaltet die 625-te Spalte von df eine Gruppierung, die auch für dfcr gültig ist?

Gruß, Jörg
Paul_CU

Re: Dppelschleife

Beitrag von Paul_CU »

jogo hat geschrieben: Mo Mai 29, 2017 8:50 am willkommen im Forum!
Danke und auch fuer deine Antwort!
jogo hat geschrieben: Mo Mai 29, 2017 8:50 am Kannst Du bitte mal erläutern, welche Verbindung zwischen den Dataframes dfcr und df besteht?
Tut mir Leid, dfcr ist ein subset von df und df in der Schleife sollte eigentlich dfcr heissen. Das aendert leider nichts am Endergebnis.

Ich merke, die Idee hinter der Doppelschleife nicht gut erklaert zu haben (bzw. mein bisheriger Ansatz ist nicht zielfuehrend). Ich habe einen Datensatz mit etwa 15,000 Leuten aus 21 Laendern. Darauf bezieht sich "ev <- 1:21" (siehe den 2.Code in meinem ersten Post). Ich moechte nun in jedem Land testen, ob zwei Gruppen ("dfcr$lr") die gleiche Varianz aufweisen (deshalb der LeveneTest, der uebrigens aus dem Package car stammt). Und das fuer 10 Variablen ("ext.var <- 614:623") in jedem der 21 Laender.
Ich stelle es mir so vor, dass der Output aus einer 210x5 Matrix besteht. Die Spalten sind die Variablen SD1, SD2, df2, F, p. Die Zeilen koennten den Output der 10 Variablen beinhalten, gruppiert nach Land. Ich hoffe, das Ziel der Doppelschleife ist etwas klarer geworden.

Paul
jogo
Beiträge: 2085
Registriert: Fr Okt 07, 2016 8:25 am

Re: Dppelschleife

Beitrag von jogo »

Paul_CU hat geschrieben: Di Mai 30, 2017 1:12 pm Ich merke, die Idee hinter der Doppelschleife nicht gut erklaert zu haben (bzw. mein bisheriger Ansatz ist nicht zielfuehrend). Ich habe einen Datensatz mit etwa 15,000 Leuten aus 21 Laendern. Darauf bezieht sich "ev <- 1:21" (siehe den 2.Code in meinem ersten Post). Ich moechte nun in jedem Land testen, ob zwei Gruppen ("dfcr$lr") die gleiche Varianz aufweisen (deshalb der LeveneTest, der uebrigens aus dem Package car stammt). Und das fuer 10 Variablen ("ext.var <- 614:623") in jedem der 21 Laender.
Es gibt also genau 21 Länder (kodiert in einer Spalte des Datensatzes). Wie wäre es denn, wenn der große Dataframe in 21 kleine Dataframes zerhackt wird (für jedes Land einen) - das macht die Funktion split() (sie erzeugt eine Liste von Dataframes). Über die Liste kann man mit lapply() bzw sapply() eine Funktion drüberjagen, die sich jedes einzelne Element (also jeweils einen Dataframe) vornimmt und auswertet.

Gruß, Jörg
p.s.: bin gerade etwas knapp mit der Zeit, melde mich später mit einigen Programmzeilen.
... so:

Code: Alles auswählen

library("car")

my.stat <- function(x, lr) c(
  sd05= sd(x[dfcr[,81] ==  5], na.rm = TRUE), 
  sd10= sd(x[dfcr[,81] == 10], na.rm = TRUE), 
  df2 = leveneTest(x ~ factor(lr))$Df[2],
  F   = leveneTest(x ~ factor(lr))$'F value'[1],
  p   = leveneTest(x ~ factor(lr))$'Pr(>F)'[1]
)

jedesLand <- function(dfcr) {
  ext.var <- 614:623
  x3 <- sapply(dfcr[ext.var], my.stat, lr=dfcr$lr)
  # colnames(x3) <- ext.var  # eventuell noch Namen setzen. Variante:
  colnames(x3) <- names(dfcr)[ext.var]
  x3
}

L <- split(df, df[, 625])
lapply(L, jedesLand)
Noch schöner wäre es, ich könnte die Programmierung test, aber ohne Daten ... :(
Kannst Du bitte mindestens mal das Ergebnis von

Code: Alles auswählen

str(df$lr)
posten?
Paul_CU

Re: Dppelschleife

Beitrag von Paul_CU »

Erstmal vielen Dank fuer den Code! Ja, den Datensatz zu posten ist schwierig. Es sind Daten vom European Social Survey (7. Runde), der aus 21 Laendern besteht. Ich habe einige Variablen transformiert, die hier die 10 abhaengigen Variablen sind.

jogo hat geschrieben: Di Mai 30, 2017 1:34 pm Kannst Du bitte mindestens mal das Ergebnis von

Code: Alles auswählen

str(df$lr)
posten?
Hier der Code fuer den Teil des Datensatzes der fuer die Diskussion mir relevant erscheint (ich habe den Datensatz in mehrere Teile zerlegt und moechte das hier Erreichte am Ende mit zwei anderen Teilen replizieren):

Code: Alles auswählen

str(dfcr$lr)
 num [1:12112] 5 10 5 5 5 5 5 5 5 5 ...
bzw. fuer den fuer meine Fragestellung vollen Datensatz

Code: Alles auswählen

str(df$lr)
 num [1:13302] 5 0 0 10 5 5 5 5 5 5 ...
Dein Code laeuft super durch, allerdings sieht das Ergebnis seltsam aus, da die Differenzen der Standardabweichungen nicht mit den p-Werten korrelieren (selbst bei gleichem Stichprobenumfang). Ich weiss nicht, inwieweit es noch moeglich ist Tipps zu geben, ohne den Datensatz zu sehen. Wenn nicht, ist es auch kein Problem. Dein Loesungsvorschlag sieht erstmal sehr gut aus und ich werde ihn aus Grundlage nehmen und das Ergebnis dann hier posten.

Paul
jogo
Beiträge: 2085
Registriert: Fr Okt 07, 2016 8:25 am

Re: Dppelschleife

Beitrag von jogo »

Hallo Paul,
Paul_CU hat geschrieben: Mi Mai 31, 2017 1:13 amHier der Code fuer den Teil des Datensatzes der fuer die Diskussion mir relevant erscheint (ich habe den Datensatz in mehrere Teile zerlegt und moechte das hier Erreichte am Ende mit zwei anderen Teilen replizieren):

Code: Alles auswählen

str(dfcr$lr)
 num [1:12112] 5 10 5 5 5 5 5 5 5 5 ...
bzw. fuer den fuer meine Fragestellung vollen Datensatz

Code: Alles auswählen

str(df$lr)
 num [1:13302] 5 0 0 10 5 5 5 5 5 5 ...
hm, dann sollte in der Funktion jedesLand() der formale Parameter anders benannt werden. Außerdem wollte ich sehen, ob die explizite Umwandlung zu Faktor, z.B. factor(dfcr$lr), notwendig ist (hätte ja sein können, dass die entsprechende Spalte schon als Faktor gespeichert ist). Also die Umwandlung ist nötig: das kann man implizit machen, indem man eine andere Aufrufkonvention für die Funktion leveneTest() nutzt: leveneTest(x, lr)
Da gibt es die entsprechenden warnings - das ist unsauber programmiert (ansonsten entspricht es dem bisherigen Vorgehen). Allerdings würde ich empfehlen, möglichst früh die Spalte $lr in einen Faktor umzuwandeln - eventuell gleich nach dem Einlesen (im Datadrame df)

Code: Alles auswählen

df$lr <- factor(df$lr) # oder df$lr <- as.factor(df$lr)
Wenn der Dataframe dfcr ein Subset von df ist, müsste die Eigenschaft, dass diese Spalte ein Faktor ist, erhalten bleiben. Ein Nachteil kann sein, dass so ein Faktor immer seine ursprünglichen Levels (Faktorstufen) mit rumschleppt - insofern kann es sein, dass Du erst im Dataframe dfcr die Spalte in einen Faktor umwandeln möchtest.
Du kannst ja einfach mal etwas rumprobieren:

Code: Alles auswählen

library("car")

my.stat <- function(x, d) { 
  lev <- leveneTest(x ~ d$lr)
  c(  sd05= sd(x[d[,81] ==  5], na.rm = TRUE), 
      sd10= sd(x[d[,81] == 10], na.rm = TRUE), 
      df2 = lev$Df[2], F = lev$'F value'[1], p = lev$'Pr(>F)'[1]
  )
}

jedesLand <- function(d) {
  ext.var <- 614:623
  x3 <- sapply(d[ext.var], my.stat, d=d)
  colnames(x3) <- names(d)[ext.var]
  x3
}

df$lr <- factor(df$lr) # oder df$lr <- as.factor(df$lr)
L <- split(df, df[, 625])
lapply(L, jedesLand)
Wenn das nicht funktioniert, bleibt es einfach bei:

Code: Alles auswählen

library("car")

my.stat <- function(x, d) { 
  lev <- leveneTest(x ~ factor(d$lr))
  c(  sd05= sd(x[d[,81] ==  5], na.rm = TRUE), 
      sd10= sd(x[d[,81] == 10], na.rm = TRUE), 
      df2 = lev$Df[2], F = lev$'F value'[1], p = lev$'Pr(>F)'[1]
  )
}

jedesLand <- function(d) sapply(d[614:623], my.stat, d=d) # ext.var <- 614:623

lapply(split(df, df[, 625]), jedesLand)
:!: Achtung, ich habe noch mal an einigen Stellen die Parameter umgestellt - ist jetzt sicherer so. :!:
Dein Code laeuft super durch, allerdings sieht das Ergebnis seltsam aus, da die Differenzen der Standardabweichungen nicht mit den p-Werten korrelieren (selbst bei gleichem Stichprobenumfang). Ich weiss nicht, inwieweit es noch moeglich ist Tipps zu geben, ohne den Datensatz zu sehen.
Freut mich, dass mein blindes Programmieren erfolgreich war - ist nicht immer ganz einfach.
Ich hoffe, Du weißt, wie bei einem t-Test t-Wert, p-value und Standardfehler des Schätzers miteinander zusammenhängen ...
Ansonsten, lass bitte mal die neue Version laufen (ich habe da so einen Verdacht, was ich evtl. vorher falsch gemacht habe).

Gruß, Jörg
Antworten