Если еще операторы, чтобы проверить, если строка содержит подстроку в R - PullRequest
0 голосов
/ 12 июня 2018

У меня есть список, который содержит несколько строк для каждого наблюдения (см. Ниже).

  [1] A, C, D 
  [2] P, O, E
  [3] W, E, W
  [4] S, B, W

Я хочу проверить, содержат ли строки определенные подстроки, и если да, вернуть соответствующую подстроку, в этом примере это будет "A" или "B" (см. Желаемый результат ниже).Каждое наблюдение будет содержать только одну из 2 подстрок (A | B)

  [1] A 
  [2] NA
  [3] NA
  [4] B

Нет. Я предпринял эту попытку для ее решения, но она кажется очень неэффективной, а также я не могу заставить ее работать.Как я мог решить это?

  if (i == "A") {
    type <- "A"
  } else if { (i == "B") 
    type <- "B" 
  } else { type <- "NA"
  } 

Примечание: мне нужно будет выполнить цикл через> 1000 наблюдений

Ответы [ 5 ]

0 голосов
/ 12 июня 2018

Если вы хотите получить список, вы можете использовать это:

library(magrittr)
x = list(
     c("A", "C", "D"), 
     c("P", "O", "E"),
     c("W", "E", "W"),
     c("S", "B", "W")
     )

myFunction <- function(x){

     x1 <- paste0(x, collapse = "")

     ifelse(stringr::str_detect(x1 , "A|B"), stringr::str_extract(x1, "A|B"), NA)
}

x %>% purrr::map(~ myFunction(.))
0 голосов
/ 12 июня 2018

Ниже мы предоставляем простые и базовые решения.Решение strapply очень короткое, но оно не будет работать, если сопоставляемые элементы могут быть подстроками цели;однако они не являются подстрокой в ​​вопросе, поэтому он должен работать там.Базовое решение будет работать даже в этом случае, поскольку оно использует точные совпадения, а не регулярные выражения.

1) strapply (gsubfn) Используйте strapply в gsubfn.Пропустите simplify=TRUE, если вы хотите список в качестве вывода.[AB] при необходимости можно заменить на A|B.

library(gsubfn)

strapply(x, "[AB]", empty = NA, simplify = TRUE)
## [1] "A" NA  NA  "B"

2) base Разделить вход и для каждого элемента разделения Отфильтровать список выдачи совпадений L.Возможно, вам достаточно L, но если нет, то последняя строка упрощает его до вектора и заменяет элементы нулевой длины на NA.

L <- lapply(strsplit(x, ", "), Filter, f = function(x) x %in% c("A", "B"))
unlist(replace(L, !lengths(L), NA))
## [1] "A" NA  NA  "B"

Примечание

x <- c("A, C, D", "P, O, E", "W, E, W", "S, B, W")
0 голосов
/ 12 июня 2018

В Base R вы можете циклически перебирать строки, чтобы обнаруживать и назначать их на выходы с [ и <- ([<-).

invec <- c(
  'A, C, D',
  'P, O, E',
  'W, E, W',
  'S, B, W')

out <- rep(NA, length(invec))
for(x in c('A', 'B')) out[grep(x, invec)] <- x
out
#[1] "A" NA  NA  "B"
0 голосов
/ 12 июня 2018

без использования пакета и работы только с векторами:

vec <- c('A, C, D', 
         'P, O, E', 
         'W, E, W', 
         'S, B, W')

ifelse(grepl('A', vec), 'A', ifelse(grepl('B', vec), 'B', NA))

Вы можете упростить это далее, но я оставил его в развернутом виде, чтобы вы могли увидеть, как он работает.

0 голосов
/ 12 июня 2018

Предполагая, что у вас есть вектор символов, вы можете использовать stringr::str_extract для этой цели:

s <- c('A, C, D', 'P, O, E', 'W, E, W', 'S, B, W')
s
# [1] "A, C, D" "P, O, E" "W, E, W" "S, B, W"
stringr::str_extract(s, 'A|B')
# [1] "A" NA  NA  "B"

Если предпочитается совпадение слов, используйте границы слов \\b:

stringr::str_extract(s, '\\b(A|B)\\b')
# [1] "A" NA  NA  "B"

Если подстрока определяется как ", ", вы можете использовать это регулярное выражение (?<=^|, )(A|B)(?=,|$):

# use the test case from G.Grothendieck
stringr::str_extract(c("A.A, C", "D, B"), '(?<=^|, )(A|B)(?=,|$)')
# [1] NA  "B"
...