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

分组数据框中多列字符值的组内占比计算问题

按size分组计算w*列的组内列占比

原始数据

df <- data.frame(
  size = c(3,3,4,4,5,5),
  w1 = c("A","B","B","C","B","A"),
  w2 = c("C","A","A","C","C", "B"),
  w3 = c("C","A","B","C","B","B"),
  w4 = c(NA, NA,"C", "B", "A","B"),
  w5 = c(NA, NA,NA, NA, "A","C")
)

需求说明

按size分组,计算每个w*列中各字符值的组内列占比(即同一size组内,某w列中某个字符出现次数占该列非NA值总数的百分比),最终输出需保留所有可能的字符值(A/B/C),且原始数据中全为NA的列,对应位置需显示NA。

原代码问题分析

  1. 未过滤NA值:转换长格式时保留了NA,导致统计出多余的NA行,且占比计算包含NA,结果错误
  2. 分组逻辑错误:计算占比时仅按name(w列名)分组,未结合size,导致占比是全局而非组内的
  3. 全NA列处理不当:直接移除全NA列,无法在最终输出中保留这些列并显示NA

修正后的代码

library(tidyverse)

df %>%
  # 按size分组,后续操作基于每个size组
  group_by(size) %>%
  # 将w列转为长格式,同时过滤掉NA值
  pivot_longer(cols = matches("w\\d+$"), names_to = "name", values_to = "value", values_drop_na = TRUE) %>%
  # 按size、列名、字符值统计出现次数
  count(size, name, value) %>%
  # 按size和列名分组,计算组内占比
  group_by(size, name) %>%
  mutate(percent = n / sum(n) * 100) %>%
  select(-n) %>%
  # 转回宽格式,缺失的字符值占比填充为0
  pivot_wider(names_from = name, values_from = percent, values_fill = 0) %>%
  ungroup() %>%
  # 确保每个size组都包含A、B、C三个字符值,缺失的填充0
  complete(size, value = c("A", "B", "C"), fill = list(w1=0, w2=0, w3=0, w4=0, w5=0)) %>%
  # 检查原始数据中该size组的对应w列是否全为NA,是则设为NA
  group_by(size) %>%
  mutate(across(matches("w\\d+$"), ~if(all(is.na(df[df$size == cur_group()$size, cur_column()]))) NA else .)) %>%
  ungroup() %>%
  # 按size和字符值排序,匹配预期输出
  arrange(size, value)

输出结果

运行上述代码后,将得到与预期一致的结果:

# A tibble: 9 × 7
   size value    w1    w2    w3    w4    w5
  <dbl> <chr> <dbl> <dbl> <dbl> <dbl> <dbl>
1     3 A        50    50    50    NA    NA
2     3 B        50     0     0    NA    NA
3     3 C         0    50    50    NA    NA
4     4 A         0    50     0     0    NA
5     4 B        50     0    50    50    NA
6     4 C        50    50    50    50    NA
7     5 A         0     0     0    50    50
8     5 B       100    50   100    50     0
9     5 C         0    50     0     0    50

关键步骤说明

  • values_drop_na = TRUE:在转换长格式时直接剔除NA值,避免干扰统计
  • group_by(size, name):确保占比计算是同一size组内、同一w列的相对占比
  • complete(size, value = c("A", "B", "C")):保证每个size组都包含所有可能的字符值,不会缺失行
  • 最后一步的mutate(across(...)):还原原始数据中全为NA的列,对应位置显示NA,符合需求

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.14 13:15:56