Фильтрация большого фрейма данных на основе значений столбцов с использованием R

#r #dataframe #filter #dplyr #data-science

Вопрос:

У меня очень большой фрейм данных с почти 502493 строками и 261 столбцом. Я хочу отфильтровать его, и мне нужны идентификаторы с конкретными кодами (коды, начинающиеся с «E»). Вот как выглядят мои данные,

Удостоверения личности код1 код2
1 C443 E109
2 AX31 М223
1 E341 QWE1
3 E131 М223

Мой необходимый вывод-идентификаторы с кодами, начинающимися только с «E».

Удостоверения личности код
1 E109
1 E341
3 E131

Я пытаюсь использовать «фильтр» пакета dplyr, но не получаю требуемого вывода. Заранее спасибо

Ответ №1:

Мы можем изменить формат на «длинный» с pivot_longer помощью и filter путем создания логического вектора из первого извлеченного символа (с substr )

 library(dplyr)
library(tidyr)
df1 %>%
   pivot_longer(cols = starts_with("code"), 
       values_to = 'code', names_to = NULL) %>%   
   filter(substr(code, 1, 1) == "E")
 

-выход

 # A tibble: 3 × 2
    IDs code 
  <int> <chr>
1     1 E109 
2     1 E341 
3     3 E131 
 

Если данные действительно большие, мы можем сделать a filter перед pivot_longer тем, как оставить только строки, имеющие по крайней мере одну букву » E » в столбце

 df1 %>%
   filter(if_any(starts_with('code'), ~ substr(., 1, 1) == 'E')) %>% 
   pivot_longer(cols = starts_with("code"), 
       values_to = 'code', names_to = NULL) %>%   
   filter(substr(code, 1, 1) == "E")
 

Если это очень большие данные, есть другой вариант data.table . Преобразуйте data.frame в ‘data.table’ ( setDT ), выполните цикл по интересующим столбцам ( .SDcols ) с lapply replace элементами , которые не начинаются с «E» NA , затем используйте fcoalesce , чтобы получить первый элемент, не являющийся NA, для каждой строки, используя do.call

 library(data.table)
na.omit(setDT(df1)[, .(IDs, code = do.call(fcoalesce, 
    lapply(.SD, function(x) replace(x, substr(x, 1, 1) != "E", 
      NA)))), .SDcols = patterns("code")])
 

-выход

    IDs code
1:   1 E109
2:   1 E341
3:   3 E131
 

данные

 df1 <- structure(list(IDs = c(1L, 2L, 1L, 3L), code1 = c("C443", "AX31", 
"E341", "E131"), code2 = c("E109", "M223", "QWE1", "M223")), 
class = "data.frame", row.names = c(NA, 
-4L))