如何在数据框上使用grep?

时间:2014-03-21 20:39:54

标签: r grep dataframe

我有以下数据框:

> 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

......我无法理解这个错误。关于如何获得预期结果的任何想法?

非常感谢

2 个答案:

答案 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,所以我认为这不会很好地扩展。