在R中为每个ID计算年度均值:按行求每12列均值的方法
解决每个ID的年度均值计算问题
你的原代码通过colMeans对每年第1个月的列求均值,得到的是所有ID在该年度首月的整体均值,而非每个ID的全年均值。要实现每个ID对应每年的均值计算,核心是先把宽格式的月度数据转为长格式,再按ID和年份分组统计。以下是几种可行的实现方法:
Base R 实现
适合不想加载额外包的场景:
# 将宽格式转为长格式,假设第一列是ID列(列名为"ID") long_df <- reshape(df, direction = "long", varying = names(df)[-1], # 指定所有月度数据列 v.names = "value", # 月度值的列名 timevar = "date", # 日期列的列名 times = names(df)[-1]) # 用原月度列名作为日期值 # 从日期列提取年份(假设列名格式为XYYYY.MM.DD,先去掉开头的X,再按.分割取第一部分) long_df$year <- sub("^X", "", long_df$date) %>% strsplit("\\.") %>% sapply(function(x) x[1]) # 按ID和年份分组计算年度均值,保留1位小数 annual_means <- aggregate(value ~ ID + year, data = long_df, FUN = function(x) round(mean(x, na.rm = TRUE), 1))
dplyr + tidyr 实现
代码更直观易读,适合日常数据分析:
library(dplyr) library(tidyr) annual_means <- df %>% # 把所有月度列转为长格式:ID保留,其他列转为日期-值对 pivot_longer(cols = -ID, names_to = "date", values_to = "value") %>% # 从日期列提取年份(适配XYYYY.MM.DD格式) mutate(year = sub("^X", "", date) %>% str_split("\\.", simplify = TRUE)[,1]) %>% # 按ID和年份分组 group_by(ID, year) %>% # 计算年度均值并保留1位小数,最后取消分组 summarise(annual_mean = round(mean(value, na.rm = TRUE), 1), .groups = "drop")
data.table 实现
处理大数据集时效率更高:
library(data.table) # 转换为data.table格式 setDT(df) annual_means <- melt(df, id.vars = "ID", variable.name = "date", value.name = "value")[, # 提取年份 year := sub("^X", "", date) %>% tstrsplit("\\.")[[1]] ][, # 按ID和年份分组计算均值 .(annual_mean = round(mean(value, na.rm = TRUE), 1)), by = .(ID, year) ]
注意事项
如果你的月度列名格式不是XYYYY.MM.DD(比如是2000_01或200001),需要调整提取年份的代码:
- 若列名是
2000_01:用year = sub("_.*", "", date)提取年份 - 若列名是
200001:用year = substr(date, 1, 4)提取年份
内容的提问来源于stack exchange,提问作者rar
相关产品推荐
相关产品推荐

