2017-03-23 55 views
0

我用dplyr我的數據來創建數據的這樣一個子集:查找字符串填寫新列

dd <- data.frame(ID = c(700689L, 712607L, 712946L, 735907L, 735908L, 735910L, 735911L, 735912L, 735913L, 746929L, 747540L), 
`1` = c("eg", NA, NA, "eg", "eg", NA, NA, NA, NA, "eg", NA), 
`2` = c(NA, NA, NA, "sk", "lk", NA, NA, NA, NA, "eg", NA), 
`3` = c(NA, NA, NA, "sk", "lk", NA, NA, NA, NA, NA, NA), 
`4` = c(NA, NA, NA, "lk", "lk", NA, NA, NA, NA, NA, NA), 
`5` = c(NA, NA, NA, "lk", "lk", NA, NA, NA, NA, NA, NA), 
`6` = c(NA, NA, NA, "lk", "lk", NA, NA, NA, NA, NA, NA)) 

我現在要檢查除ID的每一列,如果它含有的特定字符串。在這個例子中,我想爲每個包含「eg」和「0」的列的ID創建1個「1」列。同樣,還有一列告訴我在其他列中是否有「sk」或「lk」。之後,除ID之外的舊列可以從數據中刪除。框架

對我來說困難的部分是用動態數量的列來完成此操作,因爲我的dplyr-subset將根據特定情況返回不同數量的列,但我需要檢查每種情況下創建的每一個。我想首先使用unite將所有字符串放在一起,但是我會遇到同樣的問題:如何合併除第一個ID之外的所有列。

如果這可以解決在dplyr這將是完美的,但任何工作解決方案是讚賞。

結果應該是這樣的:

result <- data.frame(ID = c(700689L, 712607L, 712946L, 735907L, 735908L, 735910L, 735911L, 735912L, 735913L, 746929L, 747540L), 
with_eg = c(1, 0, 0, 1, 1, 0, 0, 0, 0, 1, 0), 
with_sk_or_lk = c(0, 0, 0, 1, 1, 0, 0, 0, 0, 0, 0)) 

回答

1

從你的描述,你想一列檢查「如」與另一列來檢查這兩個「LK」和「SK」。如果是這種情況,那麼下面的基本R方法將起作用。

dfNew <- cbind(id=dd[1], 
       eg=pmin(rowSums(dd[-1] == "eg", na.rm=TRUE), 1), 
       other=pmin(rowSums(dd[-1] == "sk" | dd[-1] == "lk", na.rm=TRUE), 1)) 

在這裏,在整個data.frame檢查(除了id列),並返回一個邏輯矩陣的「例如」存在下,rowSums添加TRUE值橫跨行,與na.rm除去在NAS ,那麼pminrowSums和1的輸出的最小值,以便將具有2的任何元素替換爲1,並保留具有0的任何值。

除了在初始邏輯矩陣中檢查是否存在「lk」或「sk」之外,該相同的邏輯適用於「其他」變量的構造。最後,data.frame返回一個3列data.frame與所需的值。

這返回

dfNew 
     ID eg other 
1 700689 1  0 
2 712607 0  0 
3 712946 0  0 
4 735907 1  1 
5 735908 1  1 
6 735910 0  0 
7 735911 0  0 
8 735912 0  0 
9 735913 0  0 
10 746929 1  0 
11 747540 0  0 
+1

也許更簡單: 'x = dd [-1] =='eg'; cbind(dd [1],1 * !! rowSums(x,na.rm = T),1 * !! rowSums(!x,na.rm = T))' –

+0

不錯。使用'1 * !!'將整數轉換爲二進制(0,1)非常酷。 – lmo

+0

或'+ !!'但它不是很明確。 –

0

下面是一個公認的哈克dplyr/purrr溶液。鑑於你的ID似乎不會像'eg','sk'或'lk'一樣,我沒有包含任何內容來不搜索ID列。

library(dplyr) 
library(purrr) 
dd %>% 
    split(.$ID) %>% 
    map_df(~ data_frame(
     ID = .x$ID, 
     eg = ifelse(any(.x == 'eg', na.rm = TRUE), 1, 0), 
     other = ifelse(any(.x == 'lk' | .x == 'sk', na.rm = TRUE), 1, 0) 
    ))