Grepl в R, чтобы найти соответствия любому списку строк символов
Можно ли использовать аргумент grepl, ссылаясь на список значений, возможно, используя оператор% in%? Я хочу взять данные ниже, и если у животного есть "собака" или "кошка", я хочу вернуть определенное значение, скажем, "сохранить"; если у него нет "собаки" или "кошки", я хочу вернуть "отбросить".
data <- data.frame(animal = sample(c("cat","dog","bird", 'doggy','kittycat'), 50, replace = T))
Теперь, если бы я просто сделал это, строго сопоставив значения, скажем, "cat" и "dog", я мог бы использовать следующий подход:
matches <- c("cat","dog")
data$keep <- ifelse(data$animal %in% matches, "Keep", "Discard")
Но использование grep или grepl относится только к первому аргументу в списке:
data$keep <- ifelse(grepl(matches, data$animal), "Keep","Discard")
возвращает
Warning message:
In grepl(matches, data$animal) :
argument 'pattern' has length > 1 and only the first element will be used
Заметьте, я видел этот поток в моем поиске, но это не работает:
grep, используя вектор символов с несколькими шаблонами
Ответы
Ответ 1
Вы можете использовать оператор "или" (|
) внутри регулярного выражения grepl
.
ifelse(grepl("dog|cat", data$animal), "keep", "discard")
# [1] "keep" "keep" "discard" "keep" "keep" "keep" "keep" "discard"
# [9] "keep" "keep" "keep" "keep" "keep" "keep" "discard" "keep"
#[17] "discard" "keep" "keep" "discard" "keep" "keep" "discard" "keep"
#[25] "keep" "keep" "keep" "keep" "keep" "keep" "keep" "keep"
#[33] "keep" "discard" "keep" "discard" "keep" "discard" "keep" "keep"
#[41] "keep" "keep" "keep" "keep" "keep" "keep" "keep" "keep"
#[49] "keep" "discard"
Регулярное выражение dog|cat
указывает механизму регулярных выражений искать либо "dog"
, либо "cat"
, и возвращает совпадения для обоих.
Ответ 2
Старайтесь избегать ifelse
как можно больше. Это, например, прекрасно работает
c("Discard", "Keep")[grepl("(dog|cat)", data$animal) + 1]
При значении 123
вы получите
## [1] "Keep" "Keep" "Discard" "Keep" "Keep" "Keep" "Discard" "Keep"
## [9] "Discard" "Discard" "Keep" "Discard" "Keep" "Discard" "Keep" "Keep"
## [17] "Keep" "Keep" "Keep" "Keep" "Keep" "Keep" "Keep" "Keep"
## [25] "Keep" "Keep" "Discard" "Discard" "Keep" "Keep" "Keep" "Keep"
## [33] "Keep" "Keep" "Keep" "Discard" "Keep" "Keep" "Keep" "Keep"
## [41] "Keep" "Discard" "Discard" "Keep" "Keep" "Keep" "Keep" "Discard"
## [49] "Keep" "Keep"
Ответ 3
Не уверен, что вы пробовали, но это работает:
data$keep <- ifelse(grepl(paste(matches, collapse = "|"), data$animal), "Keep","Discard")
Аналогично тому, как вы ответили.
Трюк использует пасту:
paste(matches, collapse = "|")
#[1] "cat|dog"
Таким образом, он создает регулярное выражение с собакой OR cat, а также будет работать с длинным списком шаблонов без ввода каждого из них.
Edit:
Если вы делаете это позже, подмножество data.frame в соответствии с записями "Keep" и "Discard", вы можете сделать это более непосредственно, используя:
data[grepl(paste(matches, collapse = "|"), data$animal),]
Таким образом, результаты для grepl
, которые являются TRUE или FALSE, используются для подмножества.