Подтвердить что ты не робот

R grep: есть ли оператор AND?

Предположим, что у меня есть следующий фрейм данных:

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

Как я могу использовать grep (или какой-либо другой инструмент), чтобы захватывать только строки, содержащие как "imageUploaded", так и "people"? Другими словами, как я могу создать подмножество, которое включает только строки со строками "imageUploaded" AND "people.jpg", независимо от порядка.

Я пробовал:

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

Есть ли оператор И? Или, возможно, другой способ получить ожидаемый результат?

4b9b3361

Ответ 1

Благодаря этому ответу это регулярное выражение работает. Вы хотите использовать grepl(), который возвращает логический индекс для вашего объекта данных. Я не буду требовать полного понимания внутренней работы регулярного выражения, но независимо:

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

grepl("(?=.*imageUploaded)(?=.*people\\.jpg)", x, perl = TRUE)
#-----
[1]  TRUE FALSE FALSE

Ответ 2

Мне нравится @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

Ответ 3

Для удобства чтения вы можете просто сделать:

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"

Ответ 4

Ниже приведена альтернатива grep с использованием hasley 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")