2016-07-17 164 views
4

我已數據集ifelse功能組中的R

ID <- c(1,1,2,2,2,2,3,3,3,3,3,4,4,4) 
Eval <- c("A","A","B","B","A","A","A","A","B","B","A","A","A","B") 
med <- c("c","d","k","k","h","h","c","d","h","h","h","c","h","k") 
df <- data.frame(ID,Eval,med) 
> df 
    ID Eval med 
1 1 A c 
2 1 A d 
3 2 B k 
4 2 B k 
5 2 A h 
6 2 A h 
7 3 A c 
8 3 A d 
9 3 B h 
10 3 B h 
11 3 A h 
12 4 A c 
13 4 A h 
14 4 B k 

我嘗試xy,由組ID和eval來創建變量。對於每個ID,if Eval = A, and med = "h" or "k",我設置x = 1,其他明智x = 0,if Eval = B and med = "h" or "k",我設置y = 1,其他明智y = 0。我用我不喜歡的方式,我得到了答案,但它看起來不是很大

df <- data.table(df) 
setDT(df)[, count := uniqueN(med) , by = .(ID,Eval)] 
setDT(df)[Eval == "A", x:= ifelse(count == 1 & med %in% c("k","h"),1,0), by=ID] 
setDT(df)[Eval == "B", y:= ifelse(count == 1 & med %in% c("k","h"),1,0), by=ID] 


    ID Eval med count x y 
1: 1 A c  2 0 NA 
2: 1 A d  2 0 NA 
3: 2 B k  1 NA 1 
4: 2 B k  1 NA 1 
5: 2 A h  1 1 NA 
6: 2 A h  1 1 NA 
7: 3 A c  3 0 NA 
8: 3 A d  3 0 NA 
9: 3 B h  1 NA 1 
10: 3 B h  1 NA 1 
11: 3 A h  3 0 NA 
12: 4 A c  2 0 NA 
13: 4 A h  2 0 NA 
14: 4 B k  1 NA 1 

那麼我要崩潰的行獲得唯一的ID,我不知道如何收行,任何想法?

輸出

ID x y 
1 0 0 
2 1 1 
3 0 1 
4 0 1 
+0

不應該的「Y」爲ID 1是0,因爲只有來港在 – akrun

+0

是啊,你說得對 – BIN

+0

對於因爲Eval是'A',med是'h',所以你的數據的第11行不應該是'1'嗎? – Maiasaura

回答

6

我們創建 'x' 和 'y' 的變量,而不NA元件直接強迫邏輯矢量爲二進制(as.integer

df[, x := as.integer(Eval == "A" & count ==1 & med %in% c("h", "k")) , by = ID] 

由 'ID' 分組同樣地,對於 'Y'

df[, y := as.integer(Eval == "B" & count ==1 & med %in% c("h", "k")) , by = ID] 

和總結它,使用any由「ID」

df[, lapply(.SD, function(x) as.integer(any(x))) , ID, .SDcols = x:y] 
# ID x y 
#1: 1 0 0 
#2: 2 1 1 
#3: 3 0 1 
#4: 4 0 1 

如果我們需要一種緊湊的方法,代替assinging(:=),我們總結由「ID」分組的輸出分組後,「評估和演示」的基礎上的條件,然後按'ID'分組,我們通過循環遍歷.SDcols中描述的列來檢查'x'和'y'中是否存在any TRUE值。

setDT(df)[, if(any(uniqueN(med)==1 & med %in% c("h", "k"))) { 
     .(x= Eval=="A", y= Eval == "B") } else .(x=FALSE, y=FALSE), 
    by = .(ID, Eval)][, lapply(.SD, any) , by = ID, .SDcols = x:y] 
# ID  x  y 
#1: 1 FALSE FALSE 
#2: 2 TRUE TRUE 
#3: 3 FALSE TRUE 
#4: 4 FALSE TRUE 

如果需要,我們可以轉換爲類似於第一種解決方案中顯示的方法的二進制。

+0

有反正我們不使用setDT(DF),計數:= uniqueN(MED),由=(ID,EVAL)。],然後如何摺疊行? – BIN

+0

@Stat更新緊湊的方法。邏輯矢量可以很容易地轉換爲二進制。 – akrun

+0

我得到了它,學習另一種方式如何使用data.table – BIN

1

這是我的dplyr解決方案,因爲我發現它比data.table更具可讀性。

library(dplyr) 
df %>% 
    group_by(ID, Eval) %>% 
    mutate(
    count = length(unique(med)), 
    x = ifelse(Eval == "A" & 
       count == 1 & med %in% c("h", "k"), 1, 0), 
    y = ifelse(Eval == "B" & 
       count == 1 & med %in% c("h", "k"), 1, 0) 
) %>% 
    group_by(ID) %>% 
    summarise(x1 = max(unique(x)), 
      y1 = max(unique(y))) 
5

的OP的目標...

「我嘗試創建變量x和y,按ID和eval。對於每一個ID,如果評估和演示= A,和值= 「H」如果Eval = B且med =「h」或「k」,則設置y = 1,否則y = 0。[...]然後,設置x = 1,否則x =我要崩潰的行獲得唯一的ID」

可以簡化爲...

對於每個ID和Eval,如果所有med值是h或所有med值是k,則標誌。

setDT(df) # only do this once 
df[, all(med=="k") | all(med=="h"), by=.(ID,Eval)][, dcast(.SD, ID ~ Eval, fun=any)] 

    ID  A  B 
1: 1 FALSE FALSE 
2: 2 TRUE TRUE 
3: 3 FALSE TRUE 
4: 4 FALSE TRUE 

要查看dcast做,讀?dcast並嘗試運行只是對自己,df[, all(med=="k") | all(med=="h"), by=.(ID,Eval)]第一部分。

的變化使用x和y的,而不是A和B是直接的,但不明智的(因爲不必要的重命名可以是混亂並導致額外的工作,當有新的評估和演示的值);並改爲1/0而不是TRUE/FALSE(因爲捕獲的值實際上是布爾值)。

+1

現在我更多地瞭解所有的()任何()和dcast在data.table – BIN

+0

這是一個很好的一個。 – akrun

1

爲您的崩潰結果行一個一個班輪解決方案:

df[,lapply(.SD,function(i) {ifelse(1 %in% i,ifelse(!0 %in% i,1,0),0)}),.SDcols=x:y,by=ID] 

    ID x y 
1: 1 0 0 
2: 2 1 1 
3: 3 0 1 
4: 4 0 1