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

R语言:如何按列名数值范围对数据框列求和?

按列名数值范围对行值分组求和的实现方法

原始数据框

# 构造示例数据框
df <- structure(list(
  V1 = c(2008L, 2011L, 2013L, 2014L, 2015L, 2016L, 2017L, 2018L, 2019L, 2020L, 2021L, 2022L),
  `11` = c(0L, 0L, 0L, 0L, 0L, 0L, 0L, 0L, 1L, 0L, 0L, 0L),
  `14` = c(0L, 0L, 0L, 0L, 0L, 0L, 0L, 0L, 0L, 0L, 1L, 0L),
  `15` = c(0L, 0L, 0L, 0L, 0L, 0L, 0L, 0L, 0L, 0L, 0L, 0L),
  `17` = c(0L, 0L, 0L, 0L, 0L, 0L, 0L, 0L, 0L, 0L, 0L, 2L),
  `19` = c(0L, 0L, 0L, 0L, 0L, 0L, 0L, 0L, 0L, 1L, 0L, 0L),
  `20` = c(1L, 0L, 0L, 0L, 0L, 0L, 0L, 0L, 0L, 2L, 0L, 0L),
  `21` = c(0L, 0L, 0L, 0L, 0L, 0L, 0L, 1L, 0L, 1L, 0L, 0L),
  `22` = c(0L, 0L, 0L, 0L, 0L, 1L, 0L, 1L, 0L, 0L, 0L, 0L),
  `24` = c(0L, 0L, 0L, 0L, 0L, 0L, 0L, 1L, 0L, 0L, 0L, 0L),
  `26` = c(0L, 0L, 0L, 0L, 0L, 0L, 0L, 0L, 0L, 0L, 1L, 0L),
  `28` = c(0L, 0L, 0L, 0L, 0L, 1L, 2L, 0L, 0L, 0L, 0L, 0L),
  `29` = c(0L, 0L, 0L, 0L, 1L, 0L, 0L, 0L, 0L, 0L, 0L, 0L),
  `3` = c(0L, 0L, 1L, 0L, 0L, 1L, 0L, 0L, 0L, 0L, 0L, 0L),
  `31` = c(0L, 0L, 0L, 0L, 0L, 0L, 0L, 0L, 0L, 2L, 0L, 0L),
  `32` = c(0L, 0L, 0L, 0L, 0L, 0L, 0L, 0L, 0L, 1L, 1L, 0L),
  `35` = c(0L, 0L, 0L, 0L, 0L, 1L, 0L, 0L, 0L, 1L, 0L, 0L),
  `37` = c(0L, 0L, 0L, 0L, 0L, 0L, 0L, 1L, 0L, 0L, 0L, 0L),
  `39` = c(0L, 0L, 0L, 0L, 0L, 0L, 0L, 1L, 0L, 0L, 0L, 0L),
  `47` = c(0L, 0L, 0L, 0L, 1L, 0L, 0L, 0L, 0L, 0L, 0L, 0L),
  `5` = c(0L, 0L, 0L, 0L, 2L, 0L, 0L, 0L, 0L, 0L, 0L, 0L),
  `51` = c(0L, 0L, 0L, 0L, 0L, 0L, 0L, 0L, 0L, 1L, 0L, 0L),
  `54` = c(0L, 0L, 0L, 0L, 1L, 0L, 0L, 0L, 1L, 0L, 0L, 0L),
  `55` = c(0L, 0L, 0L, 0L, 0L, 0L, 0L, 1L, 0L, 0L, 0L, 1L),
  `6` = c(0L, 0L, 0L, 0L, 0L, 0L, 0L, 0L, 0L, 0L, 1L, 0L),
  `63` = c(0L, 0L, 0L, 0L, 0L, 0L, 0L, 1L, 0L, 1L, 0L, 0L),
  `66` = c(0L, 1L, 0L, 0L, 0L, 0L, 0L, 0L, 0L, 0L, 0L, 0L),
  `7` = c(0L, 0L, 0L, 1L, 0L, 0L, 1L, 0L, 1L, 2L, 3L, 1L),
  `9` = c(0L, 0L, 0L, 0L, 0L, 0L, 0L, 1L, 0L, 1L, 0L, 0L),
  `91` = c(0L, 0L, 0L, 0L, 0L, 0L, 0L, 0L, 0L, 0L, 1L, 0L)
), class = "data.frame", row.names = c(NA, -12L))

需求说明

需要按列名的数值范围(0-10、11-20…91-100)对每一行的列值分组求和,得到指定的汇总结果。

问题分析

你之前尝试的代码xtabs(values~., transform(cbind(df[1],stack(df[-1])), ind = sub('.','',ind)))是按列名的第二位数字截取处理,不符合数值范围分组的逻辑,因此无法得到正确结果。


解决方案

方法1:使用tidyverse工具(dplyr + tidyr)

通过长格式转换、分组求和再转回宽格式,逻辑清晰易读:

library(dplyr)
library(tidyr)

# 1. 将宽格式数据转为长格式
df_long <- df %>%
  pivot_longer(-V1, names_to = "col_num", values_to = "value") %>%
  mutate(col_num = as.integer(col_num)) # 列名转为数值型

# 2. 定义分组区间和对应标签
breaks <- seq(0, 100, by = 10)
labels <- paste0(breaks[-length(breaks)], "-", breaks[-1])

# 3. 按年份和区间分组求和,再转回宽格式
result <- df_long %>%
  mutate(group = cut(col_num, breaks = breaks, labels = labels, include.lowest = TRUE)) %>%
  group_by(V1, group) %>%
  summarise(total = sum(value), .groups = "drop") %>%
  pivot_wider(names_from = group, values_from = total, values_fill = 0)

# 查看结果
print(result, row.names = FALSE)

方法2:使用base R实现

无需加载额外包,通过基础函数完成操作:

# 1. 提取数值列名并转为整数
col_nums <- as.integer(colnames(df)[-1])

# 2. 定义分组区间和标签
breaks <- seq(0, 100, 10)
labels <- paste0(breaks[-length(breaks)], "-", breaks[-1])

# 3. 对每一行按区间分组求和
row_sums <- t(apply(df[, -1], 1, function(row) {
  tapply(row, cut(col_nums, breaks = breaks, labels = labels, include.lowest = TRUE), sum)
}))

# 4. 组合年份列与求和结果
result_base <- cbind(df[, "V1", drop = FALSE], row_sums)
colnames(result_base) <- c("V1", labels)

# 查看结果
print(result_base)

两种方法都能生成符合预期的分组求和结果。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.18 23:20:26