2017-05-16 48 views
1

我有一個data.table,我想在某些條件下更改某些列。data.table只在某些條件下更改列

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 

我要的是,如果通過ID標記列中的所有值都NA,那麼我想要的值是5,如果只有部分是NA那麼我想要的值是分鐘,如果沒有一個是不適用我想將原始值返回。

我寫了一些ifelse語句來做到這一點,但我發現,如果標誌中沒有NAs,並且通過該值返回標誌,它將返回它看到的第一個值。

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 

爲什麼這不返回D的原始序列7 5 6?而且,有沒有簡單的方法來糾正這一點?

回答

1

any(...)返回一個邏輯值,而不是邏輯的載體,所以結果需要的flag第一要素,一樣的:

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

在你的情況,你不需要向量化ifelseif/else應該工作:

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