使用dplyr根据分组变量计算列的NA值

3

尽管我怀疑此前并未发布过类似的问题,但我找不到任何类似的问题。我的问题与 使用dplyr计算每列NA'S的百分比 相关。


在一个数据集中,每个主题都有多个观察值,不仅计算缺失数据条目的总数(即每列的总NA数量)很有用,还要计算有多少主题存在某种缺失数据。

例如,在数据集db(如下所示)中,item_1缺失了2个主题,item_2缺失了1个主题。

编辑1:我感兴趣的是每个项目有多少主题存在(任何)缺失值。即使在item_2中,主题编号1有两个缺失观察值,这也应该被视为1,因为它仍然是同一主题。

library("dplyr")

db <- data.frame(
  subject = c(1, 1, 1, 2),
  item_1 = c(NA, 2, 3, NA),
  item_2 = c(1, NA, NA, 4)
)
db
#>   subject item_1 item_2
#> 1       1     NA      1
#> 2       1      2     NA
#> 3       1      3     NA
#> 4       2     NA      4

到目前为止,我的方法是将所有单个计算绑定到一个新的data.frame中,但随着列数的增加,这很快变得混乱,并且代码编写也不好。

编辑1:然而,这显示了所需的值,因为item_1对于两个主题(1和2)缺失,并且item_2只有一个主题(主题2)缺失。

cbind(
  db %>%
    filter(is.na(item_1)) %>%
    summarise(na_item_1 = n_distinct(subject)),
  db %>%
    filter(is.na(item_2)) %>%
    summarise(na_item_2 = n_distinct(subject))
)
#>   na_item_1 na_item_2
#> 1         2         1

问题: dplyr 中是否有计算这个的方法?

理想情况下,我还想在某个地方添加缺失比例(就像下面的示例中一样):

data.frame(
  type = c("n", "proportion"),
  na_item_1 = c(2, 1.0),
  na_item_2 = c(1, 0.5)
)
#>         type na_item_1 na_item_2
#> 1          n       2.0       1.0
#> 2 proportion       1.0       0.5

此文档由 reprex package (v0.2.1) 于2019年4月16日创建。

提前致谢!


为什么item_2有一个缺失值? - NelsonGon
重点在于主题而不是价值观。我的意思是,item_2在1个主题(主题编号2)中缺少值。我将在帖子中尝试更清晰地表达这一点。 - Frederick
感谢指出 @RonakShah。这是错误的。应该是1.0,因为2个科目中有item_1的缺失。问题已经进行了更正。 - Frederick
2个回答

3
另一种使用 dplyr 的方法是先按subject分组,找出有NA值的组,然后再按列分组,计算n中所有NA值的总数,并将其除以所有subject的唯一值总数,以获得prop
library(dplyr)
library(tidyr)

db %>%
  group_by(subject) %>%
  summarise_all(~any(is.na(.))) %>%
  ungroup() %>%
  select(-subject) %>%
  gather() %>%
  group_by(key) %>%
  summarise(n = sum(value), 
            prop = n/n_distinct(db$subject))

#   key       n  prop
#   <chr>  <int> <dbl>
#1 item_1     2   1  
#2 item_2     1   0.5

1
一个不错的解决方案。只是对于不经常使用它的人来说,gather() 是从 tidyr 而不是 dplyr 中获取的。 - tmfmnk

1

另一种使用tidyverse的方式来评估每个项目和每个ID的NA数量可能是:

db %>%
 gather(var, val, -subject) %>%
 group_by(var, subject) %>%
 summarise(val = sum(is.na(val))) %>%
 spread(var, val)

  subject item_1 item_2
    <dbl>  <int>  <int>
1       1      1      2
2       2      1      0

如果您想要得到整体的NA数量和每个ID中NA的比例:
db %>%
 gather(var, val, -subject) %>%
 group_by(subject) %>%
 summarise(count = sum(is.na(val)),
           proportion = sum(is.na(val))/n())

  subject count proportion
    <dbl> <int>      <dbl>
1       1     3        0.5
2       2     1        0.5

如果您想要每个项目的缺失值数量和比例:
bind_rows(db %>%
 select(-subject) %>%
 gather(var, val) %>%
 group_by(var) %>%
 summarise(val = sum(is.na(val))) %>%
 spread(var, val) %>%
 mutate(type = "count"),
 db %>%
 select(-subject) %>%
 gather(var, val) %>%
 group_by(var) %>%
 summarise(val = sum(is.na(val))/n()) %>%
 spread(var, val) %>%
 mutate(type = "proportion"))

  item_1 item_2 type      
   <dbl>  <dbl> <chr>     
1    2      2   count     
2    0.5    0.5 proportion

或者,如果您想要每个项目中具有NA的独特主题数量和比例:

bind_rows(db %>%
 gather(var, val, -subject) %>%
 filter(is.na(val)) %>%
 group_by(var) %>%
 summarise(val = n_distinct(subject)) %>%
 spread(var, val) %>%
 mutate(type = "count"),
 db %>%
 gather(var, val, -subject) %>%
 group_by(var) %>%
 mutate(n = n_distinct(subject)) %>%
 filter(is.na(val)) %>%
 group_by(var) %>%
 summarise(val = first(n_distinct(subject)/n)) %>%
 spread(var, val) %>%
 mutate(type = "proportion"))

  item_1 item_2 type      
   <dbl>  <dbl> <chr>     
1      2    1   count     
2      1    0.5 proportion

请查看我问题中的编辑。我希望现在更清楚了。 - Frederick

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接