计算 grouped_df dplyr 中非 NA 列的数量

count number of non-NA columns in a grouped_df dplyr

我正在尝试在我的 .df 中创建一个列,它给出了(非 NA)列数的值。这在数据未分组的情况下很简单,因为我可以使用 ncol()dim(df)[2]。我的问题是尝试在 df 中的组上使用这些函数中的任何一个,特别是当我对数据进行分组时,一些列变为空(然后我将其删除,因此列大小在不同分组之间发生变化)。

示例:

data(iris)
iris$fake.dat1 <- rnorm(1:50) 
iris$fake.dat2 <- rnorm(1:50)
iris$fake.dat3 <- rnorm(1:50)
# make some groups be all NA for some columns
iris$fake.dat1[iris$Species == 'setosa'] <- NA
iris$fake.dat2[iris$Species == 'setosa' | iris$Species == 'virginica'] <- NA

我想在我的数据框中添加一列,用于计算每个物种的非 NA 列的数量。我使用了 janitor 包中的函数 remove_empty_cols

到目前为止,我已经尝试过:

iris %>%
  group_by(Species) %>%
  remove_empty_cols(.) %>%
  mutate(num.col = ncol(.))

这给出了一个全八的列。如果我将数据过滤到每个组,那么上面的内容似乎有效:

iris %>% 
  filter(Species == 'setosa') %>% 
  remove_empty_cols(.) %>% 
  mutate(num.col = ncol(.))

如有任何建议,我们将不胜感激!

这取决于变量是否可能具有 NA 对于组中的某些(但不是全部)值,以及您希望如何计算这些行或组。

如果您只想要每行的非NA值的数量,解决方案非常简单:

library(tidyverse)

# add partial NA column
iris <- iris %>% mutate(fake.dat3 = ifelse(fake.dat3 < 0, NA, fake.dat3))

iris1 <- iris %>% mutate(num.col = rowSums(!is.na(.)))

table(iris1$num.col)
#> 
#>  5  6  7  8 
#> 21 50 50 29

如果您想要计算每个组中具有一些非 NA 值的列的数量,则稍微复杂一些:

iris2 <- iris %>% 
    nest(-Species) %>% 
    mutate(num.col = map_int(data, ~sum(map_lgl(.x, ~!all(is.na(.x)))))) %>% 
    unnest()

table(iris2$num.col)
#> 
#>  5  6  7 
#> 50 50 50

如果您想要计算没有 any NA 的每个组的列数,请将 all 更改为 any:

iris3 <- iris %>% 
    nest(-Species) %>% 
    mutate(num.col = map_int(data, ~sum(map_lgl(.x, ~!any(is.na(.x)))))) %>% 
    unnest()

table(iris3$num.col)
#> 
#>  4  5  6 
#> 50 50 50

对于原始数据,所有方法都会 return 相同的结果,但如您所见,在真实数据上可能不会。