我有这个清单
Mylist <- c("orange", "apple", "cherry")
这个数据框
df<- data.frame(id = c(1,2,3), value = c("orange, peach, apple", "pineapple, mandarine, coconut", "cherry, peach"))
我希望选择 value 包含列表中一定数量元素的行。
在这个例子中,我希望看到至少有0个元素的行(至少1个)。 但是,0可以是变量。
所以,我理想的输出是
id value
1 orange, peach, apple
3 cherry, peach
我试过了,但它没有给我正确的结果。
df[sapply(strsplit(as.character(df$value), ","), function(x)
(x %in% Mylist)) > 0,];
如果有人建议我上面的代码出了什么问题我很感激。
答案 0 :(得分:2)
我们可以pattern
paste
创建'{1}}'Mylist'的元素,并使用'grep'检查它是否存在于'value'列中,并基于该<对数据集对象进行子集化< / p>
df[grepl(paste0("\\b(", paste(tolower(Mylist), collapse="|"), ")\\b"), tolower(df$value)),]
# id value
#1 1 orange, peach, apple
#3 3 cherry, peach
如果我们根据计数需要它,那么
library(stringr)
df[Reduce(`+`, lapply(Mylist, str_count, string = df$value)) > 1,]
# id value
#1 1 orange, peach, apple
答案 1 :(得分:1)
你遇到的一个问题是,如果你检查:strsplit(as.character(df$value), ",")[[1]]
,你会看到它返回# [1] "orange" " peach" " apple"
注意桃子和苹果前的空格。在不更改代码的情况下,快速解决方法是在", "
上进行拆分。
第二个问题是你的df中有"Cherry"
,但列表中有"cherry"
。 %in%只会检测精确的字符串匹配。如果有大小写差异的原因,您可以使用tolower()
之类的函数。
第三是sapply(strsplit(as.character(df$value), ", "), function(x) (x %in% Mylist))
返回一个bool列表,因此>
无法解释它(这是错误信息应该告诉你的内容)所以你可以改为{{1使用对代码的最少更改来解决您的问题。
说过最好退后一步,创建一个返回匹配项计数的函数,并将该函数传递给lappy或sapply。