包含另一个文件中字符串的 data.frame 的子集行

Subset lines of a data.frame containing a string in another file

我想对数据框 1 (df1) 的行进行子集化,这些行包含数据框 2 (df2) 中的列中的字符串。问题是 file1 将在同一列中有多个字符串。我尝试了 subset 和 grep 的几种变体,但没有成功。 这是文件的示例,以及我想要实现的结果(两者都可以):

df1

1 apple A,C,D,F  
2 pear A,D  
3 plum B,F  
4 banana K,P,Z  
5 orange B,C,D,H  

df2

A Jan  
B Feb  
C Mar  
D Apr  
E May  
F Jun  
G Jul  
H Aug  
I Sept  
J Oct 

结果 1

1 apple A,C,D,F  
2 pear A,D  
3 plum B,F  
5 orange B,C,D,H 

结果 2

1 apple A,C,D,F Jan,Mar,Apr,Jun  
2 pear A,D Jan,Apr  
3 plum B,F Feb,Jun  
5 orange B,C,D,H Feb,Mar,Apr,Aug  

这可能应该分多个步骤完成,但这里是一行:

df1[sapply(strsplit(as.character(df1[,3]),','),function(x) sum(x %in% as.character(df2[,1]))>0),]

strsplit() 函数使用定界符 , 拆分 df 的第 3 列中的值,return 是一个如下所示的列表:

[[1]]
[1] "A" "C" "D" "F"

[[2]]
[1] "A" "D"

[[3]]
[1] "B" "F"

[[4]]
[1] "K" "P" "Z"

[[5]]
[1] "B" "C" "D" "H"

现在我们要检查该列表的每个元素是否在 d2 的第 1 列中至少有一个值。一种方法是使用 %in%。如果我们将 strsplit() 的输出放入 l1,我们可以像这样测试列表的元素:

l1[[1]] %in% df2[,1]
[1] TRUE TRUE TRUE TRUE

但我们只需要知道一个是否为真:

sum(l1[[1]] %in% df2[,1])>0
[1] TRUE

因为我们想将它应用于列表的所有元素和 return 一个向量,所以我将它放入一个函数中并使用了 sapply()。与所有事情一样,可能有一种更快更简洁的方法,但这是一种方法。

使用@AnandaMahto 的splitstackshape 包,任务变得更容易。在这种方法中,我们在将目标列分成行后使用 merge。请确保您没有因素。您可以使用 sapply(df1, class) 查看。您可以使用 stringsAsFactors=FALSEdf1[] <- lapply(df1, as.character):

读取没有因素的数据
library(splitstackshape)
df1.long <- cSplit(df1, "V3", direction="long")
m <- merge(df2, df1.long, by.x='V1', by.y='V3')
result2 <- aggregate(. ~ V2.y, m, toString)
#     V2.y         V1               V2.x
# 1  apple A, C, D, F Jan, Mar, Apr, Jun
# 2 orange B, C, D, H Feb, Mar, Apr, Aug
# 3   pear       A, D           Jan, Apr
# 4   plum       B, F           Feb, Jun

数据

df <- read.table(text="1 apple A,C,D,F  
2 pear A,D  
3 plum B,F  
4 banana K,P,Z  
5 orange B,C,D,H", stringsAsFactors=FALSE)
df1 <- df[-1]

df2 <- read.table(text="A Jan  
B Feb  
C Mar  
D Apr  
E May  
F Jun  
G Jul  
H Aug  
I Sept  
J Oct ", stringsAsFactors=FALSE)