R语言:如何按Year分组批量获取多列最大值及对应Date
如何批量处理DataFrame分组后的最大值及对应日期?
我有一个名为Ak_total的DataFrame,包含3819个对象、93个变量。需求:按Ak_total$Year分组,对第6至93列的每一列,不仅计算每年的最大值,还要获取该最大值对应的Ak_total$Date(日期)。示例输出格式如下:
Year Date BetulaMAX 1998 1998-05-26 42 1999 1999-06-07 32 ... Year Date GrassMax 1998 1998-08-27 260 1999 1999-08-19 215 ...我已实现单列(Betula)的处理代码:
max_all <- function(x) if(length(x))x==max(x) Ak_max_date_Betula <- subset(Ak_total,!!ave(Betula, Year, FUN=max_all))但该代码仅能处理单列,请问是否可以一次性处理所有目标列?
当然可以一次性处理所有目标列!这里提供两种实用的方法,分别基于tidyverse工具和Base R,你可以根据自己的习惯选择:
方法一:用tidyverse工具(dplyr + tidyr)批量处理
这种方法逻辑清晰,代码可读性强,适合结构化的数据操作:
- 先加载必要的包:
library(dplyr) library(tidyr)
- 执行批量处理:
# 确定需要处理的目标列(第6到93列) target_cols <- names(Ak_total)[6:93] # 核心处理流程:转长格式→分组筛选最大值→转宽格式(可选) Ak_max_all <- Ak_total %>% # 只保留需要的列:Year、Date和目标列 select(Year, Date, all_of(target_cols)) %>% # 把宽格式转成长格式,方便按年份和变量分组处理 pivot_longer(cols = all_of(target_cols), names_to = "Variable", values_to = "Value") %>% # 按年份和变量分组,筛选出每组中值等于最大值的行 group_by(Year, Variable) %>% filter(Value == max(Value, na.rm = TRUE)) %>% ungroup() %>% # 转回宽格式,每个变量的最大值作为单独一列(列名带MAX后缀) pivot_wider(names_from = Variable, values_from = Value, names_glue = "{Variable}MAX")
如果想要像示例那样每个变量单独输出一个表格,可以在处理后拆分结果:
# 把宽格式转回长格式,再按变量拆分 max_list <- Ak_max_all %>% pivot_longer(cols = ends_with("MAX"), names_to = "Variable", values_to = "Value") %>% group_split(Variable) # 查看第一个变量的结果,比如BetulaMAX print(max_list[[1]])
方法二:用Base R批量处理
如果你不想加载额外的包,用Base R的lapply循环也能实现:
# 定义一个处理单列的函数,输入列名,输出该列的年度最大值及对应日期 get_max_with_date <- function(col_name) { # 按Year分组筛选最大值对应的行 subset(Ak_total, !!ave(Ak_total[[col_name]], Ak_total$Year, FUN = function(x) x == max(x, na.rm = TRUE))) %>% # 只保留需要的列,并给目标列加上MAX后缀 select(Year, Date, all_of(col_name)) %>% rename(!!paste0(col_name, "MAX") := all_of(col_name)) } # 获取目标列名 target_cols <- names(Ak_total)[6:93] # 循环处理所有目标列,得到一个包含每个变量结果的列表 max_results <- lapply(target_cols, get_max_with_date) # 如果你想把所有结果合并成一个大表格 combined_result <- Reduce(function(x, y) merge(x, y, by = c("Year", "Date"), all = TRUE), max_results) # 要是想逐个输出每个变量的结果,直接遍历列表就行 for (res in max_results) { print(res) }
小提示
- 如果数据里有缺失值,一定要在
max()函数里加上na.rm = TRUE,不然会得到错误的结果。 - 如果某一年中某列有多个相同的最大值,上述代码会保留所有对应的日期行。要是你只需要第一个出现的日期,可以把
x == max(x)改成x == x[which.max(x)]来调整。
内容的提问来源于stack exchange,提问作者Ewa
相关产品推荐
相关产品推荐

