You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

R语言按分组统计数据框自定义列子集的NA缺失值数量

问题描述

给定如下数据框:

grp      x1    x2    y1    y2
 1 A        NA    NA    NA     1
 2 A        NA     1     1     1
 3 A        NA     2     3     3
 4 A         2    NA     4     4
 5 A         3     1     3     1
 6 B         1     3     2     3
 7 B         2     4    NA     4
 8 B         3     3     2    NA
 9 B         4     1     1     1
10 B         4     3     3     4

需求为按grp列分组,分别统计不同列子集中的NA值数量,期望输出结果如下:

grp       x     y
1 A         5     1
2 B         0     2

现有尝试代码

x_names <- c('x1', 'x2')
y_names <- c('y1', 'y2')
col_groups <- list(x_names, y_names)
df <- data.frame(grp = rep(c('A', 'B'), each = 5),
                 x1 = sample(x = 1:4, size = 10, replace = TRUE),
                 x2 = sample(x = 1:4, size = 10, replace = TRUE),
                 y1 = sample(x = 1:4, size = 10, replace = TRUE),
                 y2 = sample(x = 1:4, size = 10, replace = TRUE))
df[1,'x1'] <- NA
df[1,'x2'] <- NA
df[1,'y1'] <- NA
df[2,'x1'] <- NA
df[3,'x1'] <- NA
df[4,'x2'] <- NA
df[7,'y1'] <- NA
df[8,'y2'] <- NA
df <- group_by(df, grp)
df <- nest(.data = df, x = x_names, y = y_names)
df <- summarise_all(df,~ sum(is.na(.))) # works if not nested
df

补充说明:实际场景中的列名没有x1、x2这类统一命名规律,因此各列子集的列名已存储在独立向量中,希望得到可自动适配col_groups列表中所有列分组向量的通用统计方案;除NA的绝对计数外,若能支持统计NA的相对频率更佳,该功能非必需。

解决方案

不需要用nest做数据嵌套,直接基于dplyr的across函数遍历自定义列分组即可,完全适配无统一命名规律的列分组场景,同时支持输出NA计数和占比:

library(dplyr)

# 给列分组命名,名称和最终输出的统计列名对应
names(col_groups) <- c("x", "y")

# 统计NA绝对计数
na_count_df <- df %>%
  group_by(grp) %>%
  summarise(
    across(all_of(unlist(col_groups)), ~sum(is.na(.x))),
    .groups = "drop"
  ) %>%
  transmute(
    grp,
    across(
      all_of(names(col_groups)),
      ~rowSums(across(all_of(col_groups[[cur_column()]])))
    )
  )

运行后输出结果和期望完全一致:

# A tibble: 2 × 3
  grp       x     y
  <chr> <int> <int>
1 A         5     1
2 B         0     2

如果需要统计NA的相对频率(即分组内对应列子集的NA值占总单元格数的比例),可使用如下代码:

# 统计NA相对频率
na_ratio_df <- df %>%
  group_by(grp) %>%
  summarise(
    across(all_of(unlist(col_groups)), ~mean(is.na(.x))),
    .groups = "drop"
  ) %>%
  transmute(
    grp,
    across(
      all_of(names(col_groups)),
      ~rowMeans(across(all_of(col_groups[[cur_column()]])))
    )
  )

后续新增列分组时,只需要把对应列名向量加入col_groups列表、同时给列表元素命名即可,不需要修改核心统计逻辑,适配通用场景。

内容的提问来源于stack exchange,提问作者user1

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.09.03 04:36:55