2017-06-01 5 views
2

Problem: Wie kann ich alle Zeilen in einer Gruppe vor dem Auftreten eines bestimmten Wertes rückwärts füllen. Ich versuche nicht, NA oder fehlenden Wert unter Verwendung zoona.locf zu füllen. Im Folgenden möchte ich alle vorherigen Zeilen in A mit 1,00 füllen, bevor die 1,00 für jede ID-Gruppe auftritt, idealerweise mit dplyr.Wert rückwärts von Vorkommen nach Gruppe füllen

Eingang:

data<- data.frame(ID=c(1,1,1,1,2,2,2,3,3,3,4,4,4,4,4), 
       time=c(1,2,3,4,1,2,3,1,2,3,1,2,3,4,5), 
       A=c(0.10,0.25,1,0,0.25,1,0.25,0,1,0.10,1,0.10,0.10,0.10,0.05)) 
ID time A 
1 1  0.10 
1 2  0.25 
1 3  1.00 
1 4  0.00 
2 1  0.25 
2 2  1.00 
2 3  0.25 
3 1  0.00 
3 2  1.00 
3 3  0.10 
4 1  1.00 
4 2  0.10 
4 3  0.10 
4 4  0.10 
4 5  0.05 

gewünschte Ausgabe:

ID time A 
1 1  1.00 
1 2  1.00 
1 3  1.00 
1 4  0.00 
2 1  1.00 
2 2  1.00 
2 3  0.25 
3 1  1.00 
3 2  1.00 
3 3  0.10 
4 1  1.00 
4 2  0.10 
4 3  0.10 
4 4  0.10 
4 5  0.05 

Antwort

6

Nachdem er von ID Gruppierung Sie die kumulative Summe von 1en überprüfen und, wo es noch unter 1 (noch nicht erschienen) , ersetzen Sie den A-Wert durch 1:

data %>% 
    group_by(ID) %>% 
    mutate(A = replace(A, cumsum(A == 1) < 1, 1)) 
# Source: local data frame [15 x 3] 
# Groups: ID [4] 
# 
# ID time  A 
# <dbl> <dbl> <dbl> 
# 1  1  1 1.00 
# 2  1  2 1.00 
# 3  1  3 1.00 
# 4  1  4 0.00 
# 5  2  1 1.00 
# 6  2  2 1.00 
# 7  2  3 0.25 
# 8  3  1 1.00 
# 9  3  2 1.00 
# 10  3  3 0.10 
# 11  4  1 1.00 
# 12  4  2 0.10 
# 13  4  3 0.10 
# 14  4  4 0.10 
# 15  4  5 0.05 

Ganz ähnlich könnte man auch cummax verwenden:

data %>% group_by(ID) %>% mutate(A = replace(A, !cummax(A == 1), 1)) 

Und hier ist ein Basis R-Ansatz:

transform(data, A = ave(A, ID, FUN = function(x) replace(x, !cummax(x == 1), 1))) 
3

Wir data.table verwenden können. Konvertiere den 'data.frame' in 'data.table' (setDT(data)), hole die Zeile, wo 'A' 1 ist, suche die Sequenz der Zeilen, benutze diese als i um die Werte in 'A' auf 1 zu setzen (:=)

library(data.table) 
setDT(data)[data[, .I[seq_len(which(A==1))], ID]$V1, A := 1][] 
# ID time A 
# 1: 1 1 1.00 
# 2: 1 2 1.00 
# 3: 1 3 1.00 
# 4: 1 4 0.00 
# 5: 2 1 1.00 
# 6: 2 2 1.00 
# 7: 2 3 0.25 
# 8: 3 1 1.00 
# 9: 3 2 1.00 
#10: 3 3 0.10 
#11: 4 1 1.00 
#12: 4 2 0.10 
#13: 4 3 0.10 
#14: 4 4 0.10 
#15: 4 5 0.05 

Oder wir ave von base R

data$A[with(data, ave(A==1, ID, FUN = cumsum)<1)] <- 1 
+0

@docendodiscimus Thanks man verwenden kann, sind Sie hier richtig. Ich hätte vorsichtiger sein sollen ... Ich denke, es wäre 'setDT (Daten) [Daten [, .I [Cumsum (A == 1) <1], ID] $ V1, A: = 1]' – akrun

Verwandte Themen