21

假设我有以下数据框:

User.Id    Tags
34234      imageUploaded,people.jpg,more,comma,separated,stuff
34234      imageUploaded
12345      people.jpg

我如何使用 grep (或其他工具)只抓取包含“imageUploaded”和“people”的行?换句话说,我如何创建一个子集,其中仅包含带有字符串“imageUploaded”和“people.jpg”的行,而不管顺序如何。

我试过了:

data.people<-data[grep("imageUploaded|people.jpg",results$Tags),]
data.people<-data[grep("imageUploaded?=people.jpg",results$Tags),]

有 AND 运算符吗?或者也许是另一种获得预期结果的方法?

4

4 回答 4

26

感谢这个答案,这个正则表达式似乎有效。您想使用grepl()which 返回一个逻辑来索引到您的数据对象。我不会声称完全理解正则表达式的内部工作原理,但无论如何:

x <- c("imageUploaded,people.jpg,more,comma,separated,stuff", "imageUploaded", "people.jpg")

grepl("(?=.*imageUploaded)(?=.*people\\.jpg)", x, perl = TRUE)
#-----
[1]  TRUE FALSE FALSE
于 2012-11-02T00:17:28.020 回答
15

我喜欢@Chase 的回答,这对我来说很有意义,但是使用人们不完全理解的结构可能有点危险。

这个答案旨在让任何想使用@thelatemail 更直接的方法的人放心,它也同样有效,并且在速度方面完全具有竞争力。这当然是我在这种情况下会使用的。(同样令人放心的是,更复杂的 Perl 兼容正则表达式因其强大的功能和易于扩展而无需支付性能成本。)

library(rbenchmark)
x <- paste0(sample(letters, 1e6, replace=T), ## A longer vector of
            sample(letters, 1e6, replace=T)) ## possible matches

## Both methods give identical results
tlm <- grepl("a", x, fixed=TRUE) & grepl("b", x, fixed=TRUE)
pat <- "(?=.*a)(?=.*b)"
Chase <- grepl(pat, x, perl=TRUE)
identical(tlm, Chase)
# [1] TRUE    

## Both methods are similarly fast
benchmark(
    tlm = grepl("a", x, fixed=TRUE) & grepl("b", x, fixed=TRUE),
    Chase = grepl(pat, x, perl=TRUE))
#          test replications elapsed relative user.self sys.self
# 2       Chase          100    9.89    1.105      9.80     0.10
# 1 thelatemail          100    8.95    1.000      8.47     0.48
于 2012-11-02T01:36:10.043 回答
10

为了可读性,你可以这样做:

x <- c(
       "imageUploaded,people.jpg,more,comma,separated,stuff",
       "imageUploaded",
       "people.jpg"
       )

xmatches <- intersect(
                      grep("imageUploaded",x,fixed=TRUE),
                      grep("people.jpg",x,fixed=TRUE)
                     )
x[xmatches]
[1] "imageUploaded,people.jpg,more,comma,separated,stuff"
于 2012-11-02T00:50:45.087 回答
1

下面是使用 hadley 的 grep 的替代方法stringr::str_detect()。这避免了使用perl=true@jan-stanstrup。此外,dplyr::filter()它将返回数据帧本身内的行,因此您永远不需要离开 df.

library(stringr)
libary(dplyr)
 x <- data.frame(User.Id =c(34234,34234,12345), 
                 Tags=c("imageUploaded,people.jpg,more,comma,separated,stuff",
                        "imageUploaded",
                        "people.jpg"))

 data.people <- x %>% filter(str_detect(Tags,"(?=.*imageUploaded)(?=.*people\\.jpg)"))
 data.people

# returns
#  User.Id                                                Tags
# 1   34234 imageUploaded,people.jpg,more,comma,separated,stuff

如果“people.jpg”总是跟随“imageUploaded”,这更简单并且有效

str_extract(x,"imageUploaded.*people\\.jpg")
于 2017-01-06T00:14:36.723 回答