使用 select_if 中的函数对 R 中的数据帧进行子集化以使其以分组变量为条件?

Subset dataframe in R using function inside select_if to make it conditional on a grouping variable?

我想使用 dplyr::select_if() 有条件地对 R 中的数据帧进行子集化。更具体地说,我有一个数据框,它由一个分组变量和许多其他包含一堆 NAs:

的变量组成
data <- tibble(group = sort(rep(letters[1:5],3)),
           var_1 = c(1,1,1,1,rep(NA,11)),
           var_2 = c(1,1,1,1,1,1,rep(NA,9)),
           var_3 = 1,
           var_4 = c(1,1,rep(NA,10),1,1,1),
           var_5 = c(1,1,1,1,1,1,NA,NA,NA,NA,NA,NA,1,1,1))

# A tibble: 15 x 6
   group var_1 var_2 var_3 var_4 var_5
   <chr> <dbl> <dbl> <dbl> <dbl> <dbl>
 1 a         1     1     1     1     1
 2 a         1     1     1     1     1
 3 a         1     1     1    NA     1
 4 b         1     1     1    NA     1
 5 b        NA     1     1    NA     1
 6 b        NA     1     1    NA     1
 7 c        NA    NA     1    NA    NA
 8 c        NA    NA     1    NA    NA
 9 c        NA    NA     1    NA    NA
10 d        NA    NA     1    NA    NA
11 d        NA    NA     1    NA    NA
12 d        NA    NA     1    NA    NA
13 e        NA    NA     1     1     1
14 e        NA    NA     1     1     1
15 e        NA    NA     1     1     1

在此数据框中,我需要识别并删除像 var_4 这样的列,在这种情况下,它们只出现在一组中(但不管它们是否出现在最后一组中:“e”) .重要的是,其他一切都必须保持不变(即我想保留看起来像 var_1var_2var_3var_5 的变量)。这是我试过的:

library(dplyr)

data %>% 
  filter(group!="e") %>%         # Ignore last group.
  select_if(~ function(col)) %>% # Write function to look for cols that only have values for one group of the total four groups remaining (a-d).
  names() -> cols_to_drop        # Save col names.

data %>% select(-cols_to_drop) -> new_data # Subset by saved col names.

不幸的是,我不知道如何在 select_if() 中编写该函数来指定分组变量条件。

我一直想知道的第二件事是我是否可以使用 select_if() 根据它包含的 NA 的百分比删除 cols。有办法吗?

我不确定 select_if 是否能够进行这样的列分组选择。

这是获取长格式数据的一种方法:

library(dplyr)

cols <- data %>% 
         filter(group != "e") %>%
         tidyr::pivot_longer(cols = starts_with('var')) %>%
         group_by(name, group) %>%
         summarise(value = any(!is.na(value))) %>%
         summarise(value = sum(value)) %>%
         filter(value > 1) %>%
         pull(name)
 
#Select the columns
data %>% select(group, cols)

#   group var_1 var_2 var_3 var_5
#   <chr> <dbl> <dbl> <dbl> <dbl>
# 1 a         1     1     1     1
# 2 a         1     1     1     1
# 3 a         1     1     1     1
# 4 b         1     1     1     1
# 5 b        NA     1     1     1
# 6 b        NA     1     1     1
# 7 c        NA    NA     1    NA
# 8 c        NA    NA     1    NA
# 9 c        NA    NA     1    NA
#10 d        NA    NA     1    NA
#11 d        NA    NA     1    NA
#12 d        NA    NA     1    NA
#13 e        NA    NA     1     1
#14 e        NA    NA     1     1
#15 e        NA    NA     1     1