如何用R对多数据框列表按标识合并并计算行均值?
问题描述
我有不同日期的高速路轮廓数据,需要计算月均速度并最终得到年均速度。目前已经用以下R脚本读取了目录下5个CSV文件,生成了包含5个数据框的列表:
# 读取速度数据 temp = list.files(pattern="*.csv") #将目录下所有csv文件存入列表 list2env( lapply(setNames(temp, make.names(gsub("*.csv$", "", temp))), read.csv), envir = .GlobalEnv) # 将当前工作空间中的所有数据框存入列表: rm(cbinded_df) df_list = lapply(ls(), get)
所有数据框都包含40752条记录和6个字段,示例数据如下:
> head(export_route_contours_2019.01.01_2019.01.03) vehicle_type time link_id link_name offset_mi length_mi source_id avg_speed units 1 all Jan 01 2019 00:00 1049879368 I-405 (N) 0.000 0.042 106+04417 68.1 mph 2 all Jan 01 2019 00:00 1049879363 I-405 (N) 0.042 0.044 106+04417 67.8 mph 3 all Jan 01 2019 00:00 1049879364 I-405 (N) 0.086 0.145 106+04417 67.8 mph 4 all Jan 01 2019 00:00 28428436 I-405 (N) 0.231 0.021 106+04418 71.3 mph 5 all Jan 01 2019 00:00 835598783 I-405 (N) 0.252 0.015 106+04418 71.3 mph 6 all Jan 01 2019 00:00 835598784 I-405 (N) 0.267 0.052 106+04418 71.3 mph
核心需求:
- 创建含40752条记录的合并数据框,存储各数据框
avg_speed的平均值 - 用循环或全局函数高效实现,避免逐个列出数据框名称
- 以
link_id与length_mi的组合作为记录标识符,确保路段数据正确关联
解决方案
方法1:dplyr + purrr高效处理(推荐)
直接通过列表操作数据,避免污染全局环境,代码简洁易维护:
library(dplyr) library(purrr) # 跳过list2env,直接读取CSV到列表(更规范) temp <- list.files(pattern = "*.csv") df_list <- map(temp, read.csv) # 合并所有数据框并计算分组均值 avg_speed_df <- df_list %>% # 给每个数据框添加来源文件名(可选,用于溯源) imap(~ mutate(.x, source_file = .y)) %>% # 合并所有数据框 bind_rows() %>% # 按路段标识分组,计算平均速度 group_by(link_id, length_mi, vehicle_type, link_name, offset_mi, source_id, units) %>% summarise(avg_speed_mean = mean(avg_speed, na.rm = TRUE), .groups = "drop")
方法2:基础R实现(无需第三方包)
如果不想加载额外包,用基础R函数完成:
# 读取CSV到列表 temp <- list.files(pattern = "*.csv") df_list <- lapply(temp, read.csv) # 提取所需字段并合并成大数据框 combined_df <- do.call(rbind, lapply(df_list, function(df) { df[, c("link_id", "length_mi", "vehicle_type", "link_name", "offset_mi", "source_id", "units", "avg_speed")] })) # 计算分组平均速度 avg_speed_df <- aggregate(avg_speed ~ link_id + length_mi + vehicle_type + link_name + offset_mi + source_id + units, data = combined_df, FUN = function(x) mean(x, na.rm = TRUE)) # 重命名均值列 names(avg_speed_df)[names(avg_speed_df) == "avg_speed"] <- "avg_speed_mean"
封装为可重复调用的函数
针对你需要处理12个月及多路段的需求,封装函数可快速复用:
calculate_avg_speed <- function(csv_dir = getwd()) { setwd(csv_dir) temp <- list.files(pattern = "*.csv") df_list <- lapply(temp, read.csv) # 合并数据并提取关键字段 combined_df <- do.call(rbind, lapply(df_list, function(df) { df[, c("link_id", "length_mi", "vehicle_type", "link_name", "offset_mi", "source_id", "units", "avg_speed")] })) # 计算均值 avg_speed_df <- aggregate(avg_speed ~ link_id + length_mi + vehicle_type + link_name + offset_mi + source_id + units, data = combined_df, FUN = function(x) mean(x, na.rm = TRUE)) names(avg_speed_df)[names(avg_speed_df) == "avg_speed"] <- "avg_speed_mean" return(avg_speed_df) } # 使用示例:传入CSV文件所在目录路径 # monthly_avg <- calculate_avg_speed("path/to/your/monthly/csvs")
关键注意点
- 避免使用
list2env将数据框放入全局环境,直接用列表处理更整洁,也不会造成环境变量混乱 - 用
link_id + length_mi作为分组键,确保每个路段的记录精准关联 - 添加
na.rm = TRUE处理可能的缺失值,防止计算出错 - 封装的函数可直接应用于不同月份的CSV目录,重复操作效率更高
内容的提问来源于stack exchange,提问作者Minna
相关产品推荐
相关产品推荐

