2017-03-11 1 views
0

R Version 3.3.2R - Werte zu Datenrahmen Subsets Zuordnung in verschachtelten for-Schleife

Ich versuche, bestimmte Werte auf eine leere Variable meiner Datenrahmen zuweisen, eine verschachtelte for-Schleife, entsprechend den Werten anderer Variablen dieses Datenrahmens. Allerdings ist die Ausgabe nicht das, was ich erwartet habe. Hier

ist ein reproduzierbares Beispiel:

id <- c("ID61", "ID61", "ID63", "ID69", "ID69", "ID69", "ID69", "ID69", "ID80", "ID80", "ID80", "ID81", "ID81", "ID81", "ID81") 
Round <- c(1, 2, 1, 1, 2, 3, 4, 5, 1, 2, 3, 1, 2, 3, 4) 
nrPosRound <- c(2, 0, 2, 15, 8, 4, 4, 0, 3, 1, 1, 0, 0, 0, 0) 
Y <- rep(NA, 15) 
df <- data.frame(id, Round, nrPosRound, Y) 

Der Datenrahmen Ich habe wie folgt aussieht:

> df 
    id Round nrPosRound Y 
1 ID61  1   2 NA 
2 ID61  2   0 NA 
3 ID63  1   2 NA 
4 ID69  1   15 NA 
5 ID69  2   8 NA 
6 ID69  3   4 NA 
7 ID69  4   4 NA 
8 ID69  5   0 NA 
9 ID80  1   3 NA 
10 ID80  2   1 NA 
11 ID80  3   1 NA 
12 ID81  1   0 NA 
13 ID81  2   0 NA 
14 ID81  3   0 NA 
15 ID81  4   0 NA 

Und ich würde es so aussehen mag, nach der for-Schleife verschachtelt :

> df 
    id Round nrPosRound Y 
1 ID61  1   2 FP 
2 ID61  2   0 FP 
3 ID63  1   2 FP 
4 ID69  1   15 FP 
5 ID69  2   8 FP 
6 ID69  3   4 FP 
7 ID69  4   4 FP 
8 ID69  5   0 FP 
9 ID80  1   3 1 
10 ID80  2   1 1 
11 ID80  3   1 1 
12 ID81  1   0 0 
13 ID81  2   0 0 
14 ID81  3   0 0 
15 ID81  4   0 0 

Was ich will, ist, den Wert zuweisen ‚1‘ auf die Variable ‚Y‘, wenn für die gleiche ‚id‘, in einem bestimmten 'Round' gibt es 3 oder mehr Positive (nrPosRound> = 3) und in den folgenden Runden gibt es mindestens 1 Positive (nrPosRound> = 1). 'Y' würde den Wert '0' zugewiesen bekommen, wenn 'nrPosRound' in jeder 'Runde' für dieselbe 'ID' '0' ist. 'Y' sollte 'FP' (False Positive) zugewiesen werden, wenn die vorherigen Bedingungen nicht erfüllt sind. Wenn es nur 1 'Round' für diese 'id' gibt, hätte 'Y' den Wert '1', wenn 'nrPosRound'> = 3 ist; Wert '0' wenn 'nrPosRound' == 0; Wert 'FP' if 'nrPosRound' < = 3.

Hier ist mein Code, mit dem verschachtelten for-Schleife:

for (i in 1:nrow(df)) { 

    current_id <- df$id[i] 
    id_group <- df[df$id == curr_id, ] 

    for (j in 1:nrow(id_group)) { 

    current_Round <- id_group$Round[j] 
    remainder_Rounds <- id_group$Round[(j+1):nrow(id_group)] 

    current_nrPos <- id_group$nrPosRound[id_group$Round == current_Round] 
    remainder_nrPos <- id_group$nrPosRound[id_group$Round %in% remainder_Rounds] 

    ifelse(curr_nrPos >= 3 & remainder_nrPos >= 1, 
      df$Y[i] <- 1, ifelse(curr_nrPos == 0 & remainder_nrPos == 0, 
             df$Y[i] <- 0, "FP")) 
    } 
} 

denke ich, das Problem zu 'remainder_nrPos' verwandt ist, seit dem 2. ifelse doesn Ich arbeite nicht wie ich gehofft habe. Ich habe viele Möglichkeiten ausprobiert, aber ich glaube nicht, dass es so funktioniert, wie ich es beabsichtigt hatte. Jede Hilfe wird geschätzt!

Antwort

0

Dies kann mit dplyr erfolgen. Im folgenden Code, ich zuerst group_by ID.

Ich erstelle eine Zwischenvariable min_from_last um zu sehen, ob es nach jeder Runde eine Null gab. Um dies zu tun, sortiere ich zuerst von zuletzt mit arrange(desc(Round)). Danach verwende ich cummin, um die kumulative min.

Dann reorder ich die Daten und führen Sie drei ifelse, um das gewünschte Ergebnis zu erhalten. BTW, du brauchst vielleicht nicht das zweite ifelse, da es vom ersten gefangen wird, aber ich habe es so aufgenommen, wie es in deiner Frage war.

id <- c("ID61", "ID61", "ID63", "ID69", "ID69", "ID69", "ID69", "ID69", "ID80", "ID80", "ID80", "ID81", "ID81", "ID81", "ID81") 
Round <- c(1, 2, 1, 1, 2, 3, 4, 5, 1, 2, 3, 1, 2, 3, 4) 
nrPosRound <- c(2, 0, 2, 15, 8, 4, 4, 0, 3, 1, 1, 0, 0, 0, 0) 
df1 <- data.frame(id, Round, nrPosRound,stringsAsFactors=FALSE) 

library(dplyr) 
df1 %>% 
group_by(id) %>% 
arrange(desc(Round)) %>% 
mutate(min_from_last=cummin(nrPosRound)) %>% 
arrange(Round) %>% 
mutate(Y= ifelse(max(nrPosRound)>=3 & min_from_last>0 ,"1", 
      ifelse(n()==1 & nrPosRound>=3,"1", 
      ifelse(max(nrPosRound)==0,"0","FP")))) 

     id Round nrPosRound min_from_last  Y 
    (chr) (dbl)  (dbl)   (dbl) (chr) 
1 ID61  1   2    0 FP 
2 ID61  2   0    0 FP 
3 ID63  1   2    2 FP 
4 ID69  1   15    0 FP 
5 ID69  2   8    0 FP 
6 ID69  3   4    0 FP 
7 ID69  4   4    0 FP 
8 ID69  5   0    0 FP 
9 ID80  1   3    1  1 
10 ID80  2   1    1  1 
11 ID80  3   1    1  1 
12 ID81  1   0    0  0 
13 ID81  2   0    0  0 
14 ID81  3   0    0  0 
15 ID81  4   0    0  0 
+0

Vielen Dank! Es ist eine elegante Lösung, und ich habe den Prozess deutlich verkompliziert. Ich habe nur hinzugefügt: 'arrangieren (id, Round)' – JoRom

0

Hier ist eine Basis R-Lösung.

id.vals <- unique(df$id) 

for (i in 1:length(id.vals)) { 
    group.ind <- df$id == id.vals[i] 
    id_group <- df[group.ind, 'nrPosRound'] 
    n <- length(id_group) 
    Y <- rep(NA, n) 
    g3 <- any(id_group >= 3) 
    a0 <- all(id_group == 0) 
    for (j in 1:n) { 
     if (g3 & all(id_group[j:n] >= 1)) Y[j] <- 1 
     else if (a0) Y[j] <- 0 
     else Y[j] <- 'FP' 
    } 
    df$Y[group.ind] <- Y 
} 
+0

Vielen Dank für Ihre Lösung, Ryan! Das ist die verschachtelte For-Schleife, die ich erreichen wollte. Es funktioniert genau so, wie ich es wollte! – JoRom

Verwandte Themen