我有以下数据框:
> my.data
A.Seats B.Seats
1 14,15 14,15,16
2 7 7,8
3 12,13 16,17
4 <NA> 10,11
我想检查列“A.Seats”中任何行内的字符串是否在“B.Seats”列的同一行中找到。所以输出看起来像这样:
A.Seats B.Seats Check
1 14,15 14,15,16 TRUE
2 7 7,8 TRUE
3 12,13 16,17 FALSE
4 <NA> 10,11 FALSE
但我不知道如何创建这个表。首先,我尝试使用grep:
grep(my.data$A.Seats,my.data$B.Seats)
但我收到以下输出
[1] 1
Warning message:
In grep(my.data$A.Seats, my.data$B.Seats) :
argument 'pattern' has length > 1 and only the first element will be used
......我无法理解这个错误。关于如何获得预期结果的任何想法?
非常感谢
答案 0 :(得分:1)
这是一种获得所需的方法
> List <- lapply(my.data, function(x) strsplit(as.character(x), ","))
> transform(my.data, Check=sapply(mapply("%in%", List[[1]], List[[2]]), any))
A.Seats B.Seats Check
1 14,15 14,15,16 TRUE
2 7 7,8 TRUE
3 12,13 16,17 FALSE
4 <NA> 10,11 FALSE
以下是使用grep
>transform(my.data,
Check=sapply(suppressWarnings(mapply("grep", List[[1]], List[[2]])), any))
答案 1 :(得分:1)
&#34; stringi&#34;库有一些矢量化函数,可能对这样的东西很有用。我会建议stri_detect()
函数。这是一个具有一些可重现的样本数据的例子。请注意第一行和最后一行中值的差异,以及根据是采用regex
还是fixed
方法得出的结果差异:
my.data <- data.frame(
A.Seats = c("14,15", "7", "12,13", NA, "14,19"),
B.Seats = c("14,15,16", "7,8", "16,17", "10,11", "14,15,16"))
my.data
# A.Seats B.Seats
# 1 14,15 14,15,16
# 2 7 7,8
# 3 12,13 16,17
# 4 <NA> 10,11
# 5 14,19 14,15,16
library(stringi)
stri_detect(my.data$B.Seats, fixed = my.data$A.Seats)
# [1] TRUE TRUE FALSE NA FALSE
stri_detect(my.data$B.Seats, regex = gsub(",", "|", my.data$A.Seats))
# [1] TRUE TRUE FALSE NA TRUE
上面的第一个选项将my.data$A.Seats
中的值视为固定字符串模式。第二个选项将其视为正则表达式以匹配任何值。
请注意,这会将NA
维护为NA
,但如果需要,可以轻松将其更改为FALSE
。
如果您不想过多考虑mapply
,可以考虑Vectorize
制作grepl
的矢量化版本。像下面这样的东西应该这样做:
vGrepl <- Vectorize(grepl)
vGrepl(my.data$A.Seats, my.data$B.Seats) # pattern is fixed
# [1] 1 1 0 NA 0
vGrepl(gsub(",", "|", my.data$A.Seats), my.data$B.Seats) # pattern is regex
# 14|15 7 12|13 <NA> 14|19
# 1 1 0 NA 1
as.logical(vGrepl(my.data$A.Seats, my.data$B.Seats)) # coerce to logical
# [1] TRUE TRUE FALSE NA FALSE
因为这会在向量中的每个元素上调用grepl
,所以我认为这不会很好地扩展。