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

R语言:如何按分组和年份统计变量值的频次与占比并生成指定数据集

问题:按分组和年份统计变量的绝对数量与相对占比

样本数据集

df <- structure(list(year = c("1", "2", "3", "1", "2", "3", "1", "2", 
"3", "1", "2", "3", "1", "2", "3", "1", "2", "3", "1", "2", "3", 
"1", "2", "3", "1", "2", "3", "1", "2", "3"), var2tab = c("1", 
"3", "1", "2", "2", "3", "3", "1", "3", "3", "3", "2", "2", "1", 
"2", "1", "1", "2", "3", "3", "1", "1", "2", "2", "2", "3", "1", 
"1", "3", "2"), group = c("1", "1", "1", "1", "1", "1", "1", 
"1", "1", "1", "1", "2", "2", "2", "2", "2", "2", "2", "2", "2", 
"2", "2", "3", "3", "3", "3", "3", "3", "3", "3")),
class = "data.frame", row.names = c(NA, -30L))

现有代码步骤

1. 索引目标列

var2use <- which(colnames(df) == "var2tab")
var2x <- which(colnames(df) == "group")

2. 统计唯一取值

years_unique <- unique(df$year)

x_unique <- unique(df[var2x])
x_unique <- unlist(x_unique)

n_years <- length(years_unique)
n_var2x <- length(x_unique)

3. 按分组生成数据框列表

my_list <- NULL
my_list <- list()
for (i in x_unique) {
  for (j in years_unique)
  {
    my_list[[i]] <- filter(df, df[var2x] == i)
  }
}

4. 尝试统计但仅实现全年份整体统计

my_df <- NULL
my_df <- list()
for (j in years_unique) {
  my_df[[j]] <- count(my_list[[j]][var2use])
  my_df[[j]]$var_rel <- my_df[[j]][, 2] / sum(my_df[[j]][, 2])
  my_df[[j]]$group <- paste0(j)
}

需求与预期输出

需要按分组+年份统计var2tab的绝对数量和相对占比,生成如下结构的数据集:

df_new <- data.frame(group = c("1", "1", "1", "2", "2", "2", "3", "3", "3"), 
                     value = c("1", "2", "3"), 
                     abs_year1 = c("1", "1", "1", "2", "2", "1", "1", "0", "1"), 
                     rel_year1 = c(".25", ".25", ".333", ".5", ".667", ".25", ".5", "0", ".333"), 
                     abs_year2 = c("1", "1", "0", "1", "0", "3", "1", "1", "2"), 
                     rel_year2 = c(".25", ".25", "0", ".25", "0", ".75", ".5", ".333", ".667"), 
                     abs_year3 = c("2", "2", "2", "1", "1", "0", "0", "2", "0"), 
                     rel_year3 = c(".5", ".5", ".667", ".25", ".333", "0", "0", ".667", "0"))

解决方案

使用dplyr和tidyr的管道操作高效实现,无需嵌套循环,适配大型数据集:

library(dplyr)
library(tidyr)

df_new <- df %>%
  # 按分组、年份、目标变量分组,统计绝对数量
  count(group, year, var2tab, name = "abs") %>%
  # 计算每个分组+年份下的相对占比
  group_by(group, year) %>%
  mutate(rel = abs / sum(abs)) %>%
  ungroup() %>%
  # 将年份转为列名,分别拆分绝对/相对值列
  pivot_wider(
    id_cols = c(group, var2tab),
    names_from = year,
    values_from = c(abs, rel),
    names_glue = "{.value}_year{year}",
    values_fill = list(abs = 0, rel = 0)
  ) %>%
  # 重命名列匹配预期输出
  rename(value = var2tab) %>%
  # 按分组和目标变量排序
  arrange(group, value) %>%
  # 格式化相对值为三位小数,去掉开头的0
  mutate(across(starts_with("rel"), ~ sprintf("%.3f", .x) %>% gsub("^0", ".", .))) %>%
  # 转换为字符类型匹配预期输出格式
  mutate(across(c(group, value, starts_with("abs")), as.character))

验证输出:

print(df_new)

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.21 16:18:18