2017-05-16 9 views
1

Ich habe eine data.table, wo ich einige Spalten unter bestimmten Bedingungen ändern möchte.data.table nur Spalten unter bestimmten Bedingungen ändern

tmp = data.table(id = rep(LETTERS[1:4], each = 3), flag = c(NA, NA, 4, NA, 5, 4, NA, NA, NA, 7, 5, 6)) 

> tmp 
    id flag 
1: A NA 
2: A NA 
3: A 4 
4: B NA 
5: B 5 
6: B 5 
7: C NA 
8: C NA 
9: C NA 
10: D 7 
11: D 5 
12: D 6 

Was ich will, ist, wenn alle Werte in der Flag-Spalte von id NA sind, dann möchte ich den Wert 5 sein, wenn nur ein Teil sind NA dann möchte ich den Wert der min sein, wenn keine sind NA Ich möchte die ursprünglichen Werte zurück.

Ich schrieb ein paar ifselse-Anweisungen, um dies zu tun, aber was ich finde ist, dass, wenn es keine NAs in der Flagge gibt, und ich Flag um diesen Wert zurückgeben wird es den ersten Wert, den es sieht, zurückgeben.

tmp[ , "flag2" := ifelse(all(is.na(flag)), 5, ifelse(any(is.na(flag)), min(flag, na.rm = TRUE), flag)), by = .(id)] 

> tmp 
    id flag flag2 
1: A NA  4 
2: A NA  4 
3: A 4  4 
4: B NA  5 
5: B 5  5 
6: B 5  5 
7: C NA  5 
8: C NA  5 
9: C NA  5 
10: D 7  7 
11: D 5  7 
12: D 6  7 

Warum gibt das nicht die ursprüngliche Sequenz von 7 5 6 für D zurück? Und gibt es eine einfache Möglichkeit, dies zu korrigieren?

Antwort

1

any(...) einen einzigen logischen Wert zurückgibt anstelle eines logischen Vektor, so das Ergebnis nimmt das erste Element flag, das gleiche wie:

ifelse(FALSE, 3, c(2,3)) 
# [1] 2 

In Ihrem Fall, Sie nicht ifelse, vektorisiert brauchen if/else sollte funktionieren:

tmp[ , "flag2" := if(all(is.na(flag))) 5 else if(any(is.na(flag))) min(flag, na.rm = TRUE) else flag, by = .(id)] 

tmp 
# id flag flag2 
# 1: A NA  4 
# 2: A NA  4 
# 3: A 4  4 
# 4: B NA  4 
# 5: B 5  4 
# 6: B 4  4 
# 7: C NA  5 
# 8: C NA  5 
# 9: C NA  5 
#10: D 7  7 
#11: D 5  5 
#12: D 6  6 
Verwandte Themen