R использование dplyr ::select() в рабочем процессе со списком столбцов

#r #dplyr #purrr

#r #dplyr #purrr

Вопрос:

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

Один из способов сделать это — использовать рабочий процесс со списком столбцов. Я бы создал фрейм данных со data списком-столбцом, содержащим фреймы данных, и cols списком-столбцом, содержащим символьные векторы.

Реальное применение этого будет включать список из 24 больших наборов данных в сочетании со списком из 24 уникальных символов vecotr. Вот минимальный пример этой структуры данных, чтобы проиллюстрировать проблему:

 set.seed(2346)
df <- tibble(
  col1 = sample(c(0,1), replace=T, size=10),
  col2 = sample(c(0,1), replace=T, size=10),
  col3 = sample(c(0,1), replace=T, size=10),
  col4 = sample(c(0,1), replace=T, size=10)
)

cols <- c("col1", "col3")

df_list_col <- tibble(
  data = list(df), 
  cols = list(cols)
)
  

df_list_col имеет структуру списка-столбца, но только в одной строке.

Мое попытанное решение — создать третий столбец списка для хранения подмножества фрейма данных. Таким образом:

 df_output <- df_list_col %>% 
  mutate(subset = select(.$data, !!.$cols))
  

Но это возвращает ошибку:

 #   Error: Problem with `mutate()` input `subset`.
# x `select()` doesn't handle lists.
# ℹ Input `subset` is `select(.$data, list(c("col1", "col3")))`.
  

Я также пытался использовать purrr::map для применения функции:

 df_output <- df_list_col %>% 
  mutate(subset = map(.$data, ~ select(.x, !!.$cols)))
  

Но это возвращает аналогичную ошибку. В обоих случаях select() вектор имен столбцов отображается как список, а не как вектор. И я в тупике, как изменить это поведение.

Заранее спасибо за любую помощь!

Ответ №1:

Оба являются list столбцами. Мы можем извлекать, вводя unlist или извлекая с [[ помощью in select

 dplyr::select(df_list_col$data[[1]], unlist(df_list_col$cols))
  

Или другой вариант с !!!

 select(df_list_col$data[[1]], !!! df_list_col$cols)
  

Или с использованием tidyverse синтаксиса

 library(dplyr)
library(purrr)
df_list_col %>% 
         mutate(subset = map2(data, cols, ~ .x %>% select(all_of(.y))))
  

-вывод

 # A tibble: 1 x 3
#  data              cols      subset           
#  <list>            <list>    <list>           
#1 <tibble [10 × 4]> <chr [2]> <tibble [10 × 2]>
  

Или с помощью pmap

 df_list_col %>%
     mutate(subset = pmap(cur_data(),  ~ select(..1, all_of(..2 ))))
  

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

1. Спасибо, как всегда, akrun, это отличные предложения. Я предпочитаю вариант с mutate() , потому что он концептуально наилучшим образом соответствует рабочему процессу со списком столбцов. Я увеличу это до реальной проблемы с данными и посмотрю, как это работает там.