Как проверить, соответствует ли строка (полностью или частично) значениям во всех столбцах фрейма данных?

#r #dataframe #function

Вопрос:

У меня есть фрейм данных:

 x1               x2 
value           12
john and bob    45
another         87
 

Я хочу проверить, есть ли строка «боб» среди всех значений. Мне нужна функция, которая будет принимать кадр данных и имя строки и вернет значение TRUE для этого кадра данных. apply(df, 1, function(r) any(r == "bob")) требуется полное совпадение, поэтому, например, это не работает:

 x1               x2 
value           12
johnandbob      45
another         87
 

Также он возвращает TRUEFALSE для каждого значения в кадре данных, поэтому, если у меня миллион значений, будет миллион TRUEFALSE. Однако мне нужен только один, есть ли среди них необходимая ценность или нет. Как это сделать?

Ответ №1:

Используйте grepl для частичного сопоставления и any получения только одного значения.

 any(grepl('bob', df$x1))
#[1] TRUE
 

Это также приведет к возврату TRUE значений , таких как 'bobby' и 'ambob' т. Д. Если вы хотите, чтобы он точно соответствовал, используйте границы слов ( \b ) вокруг них.

 any(grepl('\bbob\b', df$x1))
 

Комментарии:

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

2. Ну, R-это векторизованный язык. Таким образом, функции, такие как grepl работа со всей колонкой сразу. Вы можете написать for цикл, чтобы сделать это один за другим, и остановиться, когда найдете строку, но это будет намного неэффективнее, чем текущий ответ. Если это решение действительно медленное, вам, возможно, потребуется написать цикл, Rcpp который может ускорить его.

Ответ №2:

Мы могли бы использовать str_detect из stringr пакета:

 library(dplyr)
library(stringr)
df %>% 
    mutate(across(everything(), ~str_detect(., "bob")))
 

Выход:

   x1    x2   
  <lgl> <lgl>
1 FALSE FALSE
2 TRUE  FALSE
3 FALSE FALSE
 

Или для одной колонки a df

 any(str_detect(df$x1, "bob"))
 

Выход:

 [1] TRUE
 

Комментарии:

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

2. Попробуйте это library(stringi) stri_match_first_regex(df1$x1, "bob")