1

Ich versuche, konsekutive Zählungen aus der Noshow-Spalte nach der Spalte PatientID gruppiert. Der folgende Code, den ich verwende, ist sehr nah an den Ergebnissen, die ich erreichen möchte. Die Verwendung der Summe-Funktion gibt jedoch die Summe der gesamten Gruppe zurück. Ich möchte, dass die Summenfunktion nur die aktuelle Zeile und nur die Zeilen summiert, die eine '1' darüber haben. Im Grunde versuche ich zu zählen, wie viele Male ein Patient seinen Termin für jede Zeile notiert und dann auf 0 zurückgesetzt wird, wenn er angezeigt wird. Es scheint, als ob nur ein paar Verbesserungen an meinem unteren Code vorgenommen werden müssen. Allerdings kann ich die Antwort nirgendwo auf dieser Seite finden.So führen Sie fortlaufende Zählungen von Spalte nach Gruppe bedingt nach einer anderen Spalte

transform(df, ConsecNoshows = ifelse(Noshow == 0, 0, ave(Noshow, PatientID, FUN = sum))) 

Der obige Code erzeugt den folgenden Ausgang:

#Source: local data frame [12 x 3] 
#Groups: ID [2] 
# 
# PatientID Noshow ConsecNoshows 
#  <int> <int>   <int> 
#1   1  0    0 
#2   1  1    4 
#3   1  0    0 
#4   1  1    4 
#5   1  1    4 
#6   1  1    4 
#7   2  0    0 
#8   2  0    0 
#9   2  1    3 
#10   2  1    3 
#11   2  0    0 
#12   2  1    3 

Dies ist das, was ich wünsche:

#Source: local data frame [12 x 3] 
#Groups: ID [2] 
# 
# PatientID Noshow ConsecNoshows 
#  <int> <int>   <int> 
#1   1  0    0 
#2   1  1    0 
#3   1  0    1 
#4   1  1    0 
#5   1  1    1 
#6   1  1    2 
#7   2  0    0 
#8   2  0    0 
#9   2  1    0 
#10   2  1    1 
#11   2  0    2 
#12   2  1    0 

[UPDATE] ich würde die fortlaufende Zählung mag um eine Zeile versetzt sind Nieder.

Vielen Dank für jede Hilfe, die Sie im Voraus anbieten können!

+0

Ich wünschte, ich könnte alle Ihre Lösungen markieren, wie sie alle bereitgestellt genau so, wie ich wollte. Vielen Dank für Ihre Hilfe! –

Antwort

3

Und hier ist ein anderer (ähnlich) data.table Ansatz

library(data.table) 
setDT(df)[, ConsecNoshows := seq(.N) * Noshow, by = .(PatientID, rleid(Noshow))] 
df 
#  PatientID Noshow ConsecNoshows 
# 1:   1  0    0 
# 2:   1  1    1 
# 3:   1  0    0 
# 4:   1  1    1 
# 5:   1  1    2 
# 6:   1  1    3 
# 7:   2  0    0 
# 8:   2  0    0 
# 9:   2  1    1 
# 10:   2  1    2 
# 11:   2  0    0 
# 12:   2  1    1 

Dies ist im Grunde Gruppen von PatientID und " run-length-encoding "von Noshow und erstellt Sequenzen unter Verwendung der Gruppengrößen unter Multiplikation mit Noshow, um nur die Werte zu behalten, wenn Noshow == 1

+0

David, ich habe Ihre Antwort überprüft, weil Sie den kürzesten Code zur Verfügung gestellt haben. –

+0

Ja, alle Antworten sind sehr nett zu diesem Thread. –

+0

Nachdem ich weitere Arbeiten an meinem Modell durchgeführt habe, habe ich festgestellt, dass das Ergebnis der aufeinanderfolgenden Zählung tatsächlich um eins erhöht werden muss. Wenn also die ersten beiden Zeilen als Noshow gezählt werden, sollte die dritte Zeile eine 2 in der Spalte ConsecNoshows haben. Ist das möglich? –

2

Die direkteste Art und Weise aufeinanderfolgende Werte der Gruppe rleid von data.table, hier ist eine Option aus data.table Paket, in dem Sie Gruppendaten durch die PatientID sowie rleid von Noshow Variable zu verwenden ist. Und auch müssen Sie die cumsum Funktion eine kumulative Summe der Noshow Variable zu erhalten, anstatt sum:

library(data.table) 
setDT(df)[, ConsecNoshows := ifelse(Noshow == 0, 0, cumsum(Noshow)), .(PatientID, rleid(Noshow))] 
df 
# PatientID Noshow ConsecNoshows 
# 1:   1  0    0 
# 2:   1  1    1 
# 3:   1  0    0 
# 4:   1  1    1 
# 5:   1  1    2 
# 6:   1  1    3 
# 7:   2  0    0 
# 8:   2  0    0 
# 9:   2  1    1 
#10:   2  1    2 
#11:   2  0    0 
#12:   2  1    1 
+0

Vielen Dank für die Bereitstellung der ersten Lösung, die Psidom funktionierte. –

3

Wir können rle von base R verwenden (keine Pakete verwendet). Unter Verwendung von ave, gruppieren wir nach 'PatientID', erhalten Sie die rle von 'Noshow', multiplizieren Sie die sequence der 'Längen' mit den 'Werte' repliziert durch 'Längen', um die erwartete Ausgabe zu erhalten.

helperfn <- function(x) with(rle(x), sequence(lengths) * rep(values, lengths)) 
df$ConsecNoshows <- with(df, ave(Noshow, PatientID, FUN = helperfn)) 
df$ConsecNoshows 
#[1] 0 1 0 1 2 3 0 0 1 2 0 1 

Da die OP scheint ‚tbl_df‘ zu verwenden, um eine Lösung in dplyr würde

library(dplyr) 
df %>% 
    group_by(PatientID) %>% 
    mutate(ConsecNoshows = helperfn(Noshow)) 
#  PatientID Noshow ConsecNoshows 
#  <int> <int>   <int> 
#1   1  0    0 
#2   1  1    1 
#3   1  0    0 
#4   1  1    1 
#5   1  1    2 
#6   1  1    3 
#7   2  0    0 
#8   2  0    0 
#9   2  1    1 
#10   2  1    2 
#11   2  0    0 
#12   2  1    1 
+1

Akrun, vielen Dank für Ihre Lösungen. Sie alle arbeiteten genau wie beabsichtigt. Ich mag besonders die von Ihnen zur Verfügung gestellte Basis-R-Lösung. –

3

ist ich eine Hilfsfunktion schaffen würde dann zu verwenden, was Implementierung Sie am bequemsten mit:

sum0 <- function(x) {x[x == 1]=sequence(with(rle(x), lengths[values == 1]));x} 

#base R 
transform(df1, Consec = ave(Noshow, PatientID, FUN=sum0)) 

#dplyr 
library(dplyr) 
df1 %>% group_by(PatientID) %>% mutate(Consec=sum0(Noshow)) 

#data.table 
library(data.table) 
setDT(df1)[, Consec := sum0(Noshow), by = PatientID] 
    # PatientID Noshow Consec 
    #  <int> <int> <int> 
    # 1   1  0  0 
    # 2   1  1  1 
    # 3   1  0  0 
    # 4   1  1  1 
    # 5   1  1  2 
    # 6   1  1  3 
    # 7   2  0  0 
    # 8   2  0  0 
    # 9   2  1  1 
    # 10   2  1  2 
    # 11   2  0  0 
    # 12   2  1  1 
+0

Pierre, Ihre Lösung ist sehr hilfreich, da sie mir mehrere Optionen bietet. Danke, dass Sie mich auf die Verwendung einer Hilfsfunktion aufmerksam gemacht haben. –

Verwandte Themen