В R выберите достаточное количество строк во фрейме данных, чтобы ни один столбец не был пустым

#r #dataframe #purrr #na

Вопрос:

У меня есть большой df фрейм данных в R со многими столбцами, многими NAs, но ни один столбец не является полностью NA. Меня интересует конкретный список col_list этих столбцов. Мне нужен образец фрейма данных, чтобы каждый столбец был представлен хотя бы один раз.

Моя мысль состояла в том, чтобы «перебрать» список map_dfr столбцов, отфильтровав df их там, где каждый столбец не является NA, а затем выбрать оттуда одну строку, как показано ниже.

 library(tidyverse)

col_list %>% 
  map_dfr(function(name){
    df %>% 
      filter(!is.na(name)) %>% 
      sample_n(1)
  }) %>% 
  select(all_of(col_list))
 

К сожалению, некоторые столбцы в результате все еще оказываются пустыми. Судя по всему, те несколько столбцов, которые продолжают оставаться пустыми, имеют объем памяти выше среднего для кадра данных, но я знаю, что они не совсем пустые.

Я не могу поделиться своим набором данных и не могу придумать, как воспроизвести его на меньшем наборе данных, поэтому, к сожалению, я не могу создать reprex.

В чем может быть пробел в моей логике выше, и как его можно улучшить, чтобы не было столбцов во всех NA?

Изменить: Я принял первое решение ниже. Я также решил эту проблему с помощью лучшего выбора переменных env, поэтому я публикую здесь для потомков.

 library(tidyverse)

col_list %>% 
  map_dfr(function(name){
    df %>% 
      filter(!is.na(.data[[name]])) %>%
      sample_n(1)
  }) %>% 
  select(all_of(col_list))
 

Ответ №1:

Вот воспроизводимый пример (основанный на моем лучшем понимании вашего вопроса):

 library(tidyverse)

df <- tibble(
  x = c('hello', 'yes', 'no', NA), 
  y = c(NA, NA, NA, 'hi'), 
  z = c(1, 2, 3, 4)
)

col_list <- names(df)

col_list %>% 
  map_dfr(function(name){
    df %>% 
      filter(!is.na(name)) %>% 
      sample_n(1)
  }) %>% 
  select(all_of(col_list))
 

В этом сценарии filter() функция ищет столбец с именем name , которого (вероятно) не существует. Вы могли бы завернуться name , !!sym() и это должно сработать.

 col_list %>% 
  map_dfr(function(name){
    df %>% 
      filter(!is.na(!!sym(name))) %>% 
      sample_n(1)
  }) %>% 
  select(all_of(col_list))
 

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

1. Спасибо. Я также обнаружил, что замена name на .data[[name]] исправляет это с точки зрения аккуратной оценки. Мне придется узнать об этом побольше.