在 R 中,在数据框中采样足够多的行,没有一列是空的

In R, sample enough rows in a dataframe that no column is empty

我在 R 中有一个大型数据框 df,其中有很多列,很多 NA,但没有一列完全是 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))

不幸的是,结果中的某些列仍然为空。从它的外观来看,不断出现的几列空的数据帧的 NA 数量高于平均水平,但我知道它们并不完全是空的。

我无法分享我的数据集,我想不出如何在较小的数据集上重现它,所以很遗憾我无法生成 reprex。

我上面的逻辑中的差距是什么,如果不让所有列都为 NA,如何改进?

编辑:我接受了下面的第一个解决方案。我也用更好的 env-variable selection 解决了它,所以我在这里发帖以供后代使用。

library(tidyverse)

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

这是一个可重现的例子(基于我对你的问题的最佳理解):

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))