R语言如何跨不同文件夹批量对文件应用统一处理函数
问题描述
我数年前开始接触R语言,它在数据框清洗、数据准备及其他基础任务处理场景中十分便捷实用。
目前我需要用R对存储在不同文件夹下的大量文件执行统一的基础处理操作:自动遍历dataset_2006、dataset_2007两个文件夹,完成shapefile合并、csv合并、表关联筛选、结果导出的全流程,替代现有重复编写的脚本。
现有重复逻辑的脚本如下:
library(dplyr) library(readr) library(sf) library(purrr) setwd("C:/Users/Downloads/global_data/dataset_2006") shp2006 <- list.files(pattern = 'data_2006.*\\.shp$', full.names = TRUE) listOfShp <- lapply(shp2006, st_read) combinedShp <- do.call(what = sf:::rbind.sf, args=listOfShp) #import and merge CSV files into one data frame folderfiles <- list.files(pattern = 'csv_2006_.*\\.csv$', full.names = TRUE) csv_data <- folderfiles %>% set_names() %>% map_dfr(.f = read_delim, delim = ";", .id = "file_name") new_shp_2006 <- merge(combinedShp, csv_data , by = "ID") %>% filter(label %in% c("AR45T", "GK879")) st_write(new_shp_2006 , "new_shp_2006.shp", overwrite = TRUE) setwd("C:/Users/Downloads/global_data/dataset_2007") shp2007 <- list.files(pattern = 'data_2007.*\\.shp$', full.names = TRUE) listOfShp <- lapply(shp2007, st_read) combinedShp <- do.call(what = sf:::rbind.sf, args=listOfShp) #import and merge CSV files into one data frame folderfiles <- list.files(pattern = 'csv_2007_.*\\.csv$', full.names = TRUE) csv_data <- folderfiles %>% set_names() %>% map_dfr(.f = read_delim, delim = ";", .id = "file_name") new_shp_2007 <- merge(combinedShp, csv_data , by = "ID") %>% filter(label %in% c("AR45T", "GK879")) st_write(new_shp_2007 , "new_shp_2007.shp", overwrite = TRUE)
优化实现
核心思路是把单年份的处理逻辑封装为通用函数,避免反复修改工作目录、重复编写相同逻辑,后续新增处理年份只需要往配置列表里加对应值即可,不需要改动核心处理代码。
优化后的代码如下:
library(dplyr) library(readr) library(sf) library(purrr) # 根目录配置:所有dataset_*文件夹的上级路径 root_path <- "C:/Users/Downloads/global_data" # 待处理年份配置:后续新增年份直接往向量里追加即可 target_years <- c(2006, 2007) # 筛选标签配置,需要调整筛选规则直接改这里 filter_labels <- c("AR45T", "GK879") # 单年份数据处理通用函数 process_year_data <- function(year, root_dir, filter_tags) { # 拼接对应年份的文件夹完整路径,不需要切换工作目录 year_folder <- file.path(root_dir, paste0("dataset_", year)) # 读取并合并当年所有shp文件 shp_files <- list.files(year_folder, pattern = paste0('data_', year, '.*\\.shp$'), full.names = TRUE) combined_shp <- map_dfr(shp_files, st_read) # 读取并合并当年所有csv文件 csv_files <- list.files(year_folder, pattern = paste0('csv_', year, '_.*\\.csv$'), full.names = TRUE) csv_combined <- csv_files %>% set_names() %>% map_dfr(read_delim, delim = ";", .id = "file_name") # 表关联并按规则筛选 final_data <- merge(combined_shp, csv_combined, by = "ID") %>% filter(label %in% filter_tags) # 结果导出到对应年份文件夹 output_path <- file.path(year_folder, paste0("new_shp_", year, ".shp")) st_write(final_data, output_path, overwrite = TRUE) return(invisible(final_data)) } # 批量遍历所有目标年份执行处理 walk(target_years, ~process_year_data(.x, root_path, filter_labels))
优化说明
- 移除了
setwd切换工作目录的逻辑,全程通过路径拼接定位文件,不会因为工作目录混乱出现文件找不到的报错 - 重复处理逻辑封装为独立函数,代码冗余度大幅降低
- 合并shp时直接用
map_dfr实现,替代原来lapply + 手动调用sf包内部函数rbind.sf的写法,更稳定,不会因为sf包版本更新出现内部函数变动的问题 - 所有可变配置(根路径、待处理年份、筛选标签)统一抽离到代码开头,调整参数不需要翻找核心处理逻辑
- 用
walk执行批量导出操作,是purrr包处理带副作用的批量操作的标准写法,执行效率更高
内容的提问来源于stack exchange,提问作者zakros
相关产品推荐
相关产品推荐

