包含另一个文件中字符串的 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=FALSE
或 df1[] <- 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)
我想对数据框 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=FALSE
或 df1[] <- 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)