2016-06-29 9 views
0

Ich habe Dataset folgenden auf vorhergehenden Wert basierend ändern:Variablenwerte

df <- data.frame(subject = c(1,1,1,1,1,1,1,1,1,1,1,1,2,2,2,2,2,2,2,2,2,2,3,3,3,3,3,3,3,3,3,3,3), 
      time = c(1,2,3,4,5,6,7,8,9,10,11,12,1,2,3,4,5,6,7,8,9,10,1,2,3,4,5,6,7,8,9,10,11), 
      performance = c(1,0,-1,-1,0,1,1,-1,0,0,0,1,1,1,-1,0,1,1,-1,0,0,1,-1,1,1,0,1,1,-1,0,-1,-1,0)) 

Was würde ich zu tun ist, wie einige der Einträge in der Leistungsvariable zu ändern. Genauer gesagt, wenn einem Eintrag "-1" eine "1" vorangestellt ist, möchte ich "-1" in "0" ändern.

Dies sollte jedoch nur innerhalb von Fächern erfolgen, nicht jedoch über Fächer hinweg (alle Fächer haben eine unterschiedliche Anzahl von Sitzungen).

Also, das ist, was ich möchte am Ende haben:

df2 =data.frame(subject = c(1,1,1,1,1,1,1,1,1,1,1,1,2,2,2,2,2,2,2,2,2,2,3,3,3,3,3,3,3,3,3,3,3), 
         time = c(1,2,3,4,5,6,7,8,9,10,11,12,1,2,3,4,5,6,7,8,9,10,1,2,3,4,5,6,7,8,9,10,11), 
         performance = c(1,0,-1,-1,0,1,1,0,0,0,0,1,1,1,0,0,1,1,0,0,0,1,-1,1,1,0,1,1,-1,0,-1,-1,0)) 

Hat jemand eine Idee, wie dies zu tun?

Vielen Dank im Voraus! S.

Antwort

1

Hier ist ein data.table Ansatz, wo ich eine flag Säule zuerst erstellen, die dann die Daten und aktualisiert die performance Spalte durch Referenz verwendet wird, der Teilmenge.

Ich entschied mich, es mit einer Zwischenflag-Spalte zu tun, weil ich erwarte, dass es sehr gut für große Datensätze funktioniert. Wenn Leistung nicht Ihr Interesse ist, könnten Sie natürlich ifelse oder replace stattdessen verwenden.

+0

Haben Sie erhalten auch 0 für Wert 29? – Sotos

+0

@Sotos, ja ich mache –

+0

Ok gut :) .... – Sotos

2

dplyr Verwendung,

df %>% 
    group_by(subject) %>% 
    mutate(performance = replace(performance, which(performance + lag(performance)==0 & performance == -1), 0)) 
+1

Danke, das funktioniert perfekt !! –

0

Dies ist hässlich, aber funktionieren sollte:

dftest <- df 
for (i in 2:nrow(dftest)) { 
    if(
    dftest$performance[i] == -1 && dftest$performance[i - 1] == 1 
){ 
    if(
     dftest$subject[i] == dftest$subject[i - 1] 
    ) { 
     dftest$performance[i] <- 0 
    } 
} 
} 

all.equal(df2, dftest) # ONE ERROR 

Dieser Fehler in Zeile 29 gibt - können Sie überprüfen, ob Ihr Beispiel df2 hier richtig? Wenn ich die Frage richtig verstehe, sollte df2$performance[29]0 sein?

+0

Ich glaube, das ist am besten geeignet, wenn 'df $ subject' bestellt wird. Beachten Sie, dass Sie in R die Schleife vermeiden können, da alle relationalen Operationen auf "Vektoren" ausgeführt werden. I.e. das obige übersetzt zu der effizienteren 'df $ leistung [c (FALSCH, df $ subjekt [-1] == df $ subjekt [-nrow (df)]) & c (FALSCH, (df $ performance [-nrow (df)] == 1L) & (df $ performance [-1] == -1L))] = 0' –

+0

Ja, ich habe nicht über den ungeordneten Fall nachgedacht. Wie für die Schleife - ja, ich persönlich mag die dplyr Lösung am meisten, ich bin nur irgendwie gewohnt, Schleifen zu verwenden ... – luoar

+0

Richtig, Linie 29 sollte eine 0 sein! Danke für Ihre Hilfe! –

0

Eine Lösung Basis R mit by und sapply:

gr <- do.call(c, by(df, df$subject, function(x) { 
c(FALSE, unlist(sapply(1:length(x$performance), 
function(y) (x$performance[y] == -1) & (x$performance[y-1] == 1)))) 
})) 
df[gr, 3] <- 0 
cbind(df, df2)