如何按列名模式批量计算tibble中的每日平均温度?
批量计算每日平均气温的高效解决方案
问题背景
现有如下tibble格式的温度数据,包含受访者ID及调查前后多日的最高温(tmax前缀)和最低温(tmin前缀)列:
> merged_data # A tibble: 168,747 × 15 person_id tmax_3 tmax_2 tmax_1 tmax0 tmax1 tmax2 tmax3 tmin_3 tmin_2 tmin_1 tmin0 tmin1 tmin2 <chr> <dbl> <dbl> <dbl> <dbl> <dbl> <dbl> <dbl> <dbl> <dbl> <dbl> <dbl> <dbl> <dbl> 1 0101500002010… 21.6 21.0 21.3 22.0 22.6 20.0 22.4 11.7 11.2 11.6 14.0 11.2 12.4 2 0101500002010… 21.6 21.0 21.3 22.0 22.6 20.0 22.4 11.7 11.2 11.6 14.0 11.2 12.4 # ℹ 168,737 more rows # ℹ 1 more variable: tmin3 <dbl> # ℹ Use `print(n = ...)` to see more rows
需求是高效计算每日平均气温(当日最高温+最低温的平均值),替代重复的mutate操作,尤其适合存在调查前后各100天温度列的场景。此前使用的ChatGPT代码因列名匹配错误无法运行。
原代码问题分析
ChatGPT推荐的代码存在两个核心问题:
- 列名匹配错误:
paste0("tmin_", cur_column())会将tmax_3拼接成tmin_tmax_3,并非对应的tmin_3列; rowwise()会大幅降低大数据集的处理效率,16万行的数据集运行速度极慢。
高效解决方案
方案一:使用across结合列名替换(推荐,高效向量操作)
利用across批量处理tmax列,通过字符串替换匹配对应的tmin列,无需逐行操作:
library(dplyr) library(stringr) merged_data <- merged_data %>% mutate( across( starts_with("tmax"), ~ (.x + get(str_replace(cur_column(), "^tmax", "tmin"))) / 2, .names = "tavg{str_replace(.col, 'tmax', '')}" ) )
说明:
str_replace(cur_column(), "^tmax", "tmin")将当前tmax列名替换为对应的tmin列名(如tmax_3→tmin_3,tmax3→tmin3);.names参数直接生成目标列名(如tmax_3→tavg_3,tmax0→tavg0);- 全程为向量化操作,处理16万行数据效率远高于
rowwise()。
方案二:使用pivot转换(直观,适合多列场景)
通过长表-宽表转换的方式,将同天数的tmax和tmin聚合计算后再转回宽表,代码更简洁直观:
library(dplyr) library(tidyr) merged_data <- merged_data %>% # 转换为长表,拆分出温度类型(tmax/tmin)和天数后缀 pivot_longer( cols = starts_with(c("tmax", "tmin")), names_to = c(".value", "day"), names_pattern = "(tmax|tmin)(.*)" ) %>% # 计算每日平均气温 mutate(tavg = (tmax + tmin) / 2) %>% # 转回宽表,恢复原列结构 pivot_wider( names_from = day, values_from = c(tmax, tmin, tavg) ) %>% # 保持person_id在第一列 select(person_id, everything())
说明:
names_pattern = "(tmax|tmin)(.*)"将列名拆分为温度类型和天数部分(如tmax_3拆分为tmax和_3);- 该方法无需手动处理列名匹配,适合列数极多(如前后100天)的场景,逻辑更清晰。
内容的提问来源于stack exchange,提问作者Alonso Quijano
相关产品推荐
相关产品推荐

