在data.frame中查找字符串以填充新列

时间:2017-03-23 12:51:58

标签: r dataframe dplyr

我在我的数据上使用了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以外的每一列,如果它包含某些字符串。在这个例子中,我想为每个ID创建一个带有“1”的列,其中包含一个带有“eg”和“0”的列。同样,还有一列告诉我其他列中是否有“sk”或“lk”。之后,可以从data.frame

中删除除ID以外的旧列

对我而言,困难的部分是使用动态数量的列,因为我的dplyr - 子集将根据具体情况返回不同数量的列,但我需要检查每个列中创建的列每个案例。我想首先使用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))

2 个答案:

答案 0 :(得分:1)

根据您的描述,您希望一列检查&#34;例如&#34;和另一列检查&#34; lk&#34;和&#34; sk&#34;。如果是这种情况,那么以下基本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))

这里存在&#34;例如&#34;检查整个data.frame(id列除外)并返回逻辑矩阵,rowSums在行中添加TRUE值,na.rm删除NA,然后pminrowSums和1的最小输出,以便将2的所有元素替换为1,并保留任何0的值。

同样的逻辑适用于&#34;其他&#34;变量,除了存在&#34; lk&#34;或&#34; sk&#34;在初始逻辑矩阵中检查。最后,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 :(得分:0)

这是一个公认的hapy dplyr / purrr解决方案。鉴于您的ID似乎并不相同,例如&#39;,&#39; sk&#39;或者&#39; lk&#39;,我没有&#39; ; t包含任何不搜索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)
    ))