如何用dplyr优雅实现24组对应小时列的批量求和?
解决方案
针对批量按小时匹配求和的需求,推荐几种简洁优雅的实现方式:
方法1:使用dplyr的across动态处理(最简洁)
利用across选中所有.x结尾的列,匹配对应.y列求和,自动生成.tot结尾的新列:
library(dplyr) library(stringr) a <- tibble(s1.x=2:7, s2.x=3:8, s1.y=4:9, s2.y=5:10) a %>% mutate( across( ends_with(".x"), ~ . + get(str_replace(cur_column(), "\\.x$", "\\.y")), .names = "{str_replace(.col, '\\.x$', '.tot')}" ) )
ends_with(".x"):筛选所有以.x结尾的小时列str_replace(cur_column(), "\\.x$", "\\.y"):将当前列名的.x替换为.y,获取对应y列数据.names参数:自动将新列名的.x替换为.tot
方法2:长格式转换后求和(更直观)
先将宽格式数据转成长格式,按小时分组求和后再转回宽格式,适合需要中间查看分组数据的场景:
library(tidyr) library(dplyr) a %>% # 转成长格式,提取小时数和分组(x/y) pivot_longer( everything(), names_to = c("hour", "group"), names_pattern = "s(\\d+)\\.(.)" ) %>% # 按小时分组求和 group_by(hour) %>% summarise(tot = sum(value)) %>% # 转回宽格式,调整列名 pivot_wider( names_from = hour, values_from = tot, names_prefix = "s" ) %>% rename_with(~ str_replace(., "^s", "s\\."), everything()) %>% # 和原数据合并 bind_cols(a, .)
方法3:purrr循环生成新列
通过循环1到24的小时数,批量创建求和列:
library(purrr) library(dplyr) a %>% mutate( map_dfc( 1:24, ~ tibble(!!paste0("s", .x, ".tot") := !!sym(paste0("s", .x, ".x")) + !!sym(paste0("s", .x, ".y"))) ) )
map_dfc:将每个循环生成的单列tibble按列合并!!和sym:实现字符串到列名符号的转换,动态调用列数据
内容的提问来源于stack exchange,提问作者MPB_2022
相关产品推荐
相关产品推荐

