如何在R中批量处理多个.bil文件并自动命名输出文件
问题
需要对400个不同的.bil数据集执行数据转换操作,已掌握单个文件的处理方法,但自动化处理时遇到问题——无法自动从原.bil文件名提取编号来命名输出的Shapefile和CSV文件。
单个.bil文件处理代码
library(cruts) library(raster) library(sf) library(rgdal) library(terra) require(rgdal) rdata <- "G:/Mon Drive/Doctorat/Données/Donnée spatiale indonésie/CHIRPS brut/chirps-v2.0_201410/chirps-v2.0_201410.bil" sdata <- readOGR("G:/Mon Drive/Doctorat/Données/Donnée spatiale indonésie","sub_pro_indon") r <- raster(rdata) r.vals <- extract(r, sdata) r.mean <- unlist(lapply(r.vals, FUN=mean)) sdata@data <- data.frame(sdata@data, mean=r.mean) # Write results writeOGR(sdata,"G:/Mon Drive/Doctorat/Données/Donnée spatiale indonésie/mean.shp", "mean", driver="ESRI Shapefile") write.csv2(sdata, "G:/Mon Drive/Doctorat/Données/Donnée spatiale indonésie/mean.csv")
尝试的自动化代码(存在问题)
wd <- "G:/Mon Drive/Doctorat/Données/Donnée spatiale indonésie/CHIRPS brut" setwd(wd) files <- list.files(pattern = ".bil") mean_calc <- function(X){ r <- raster(rdata) r.vals <- extract(r, sdata) r.mean <- unlist(lapply(r.vals, FUN=mean)) sdata@data <- data.frame(sdata@data, mean=r.mean) writeOGR(sdata,"G:/Mon Drive/Doctorat/Données/Donnée spatiale indonésie/CHIRPS moyenne/201410pre_mean.shp", "201410pre_mean", driver="ESRI Shapefile") write.csv2(sdata, "G:/Mon Drive/Doctorat/Données/Donnée spatiale indonésie/CHIRPS moyenne/201410pre_mean.csv") } sdata <- readOGR("G:/Mon Drive/Doctorat/Données/Donnée spatiale indonésie","sub_pro_indon") rdata <- "G:/Mon Drive/Doctorat/Données/Donnée spatiale indonésie/CHIRPS brut/chirps-v2.0_201410.bil" lapply(rdata, mean_calc)
解决方案
核心改进点
- 正确遍历所有.bil文件:原代码仅处理单个文件,需改为遍历
files列表并将每个文件名传入函数。 - 自动提取文件名编号:用字符串处理工具从
.bil文件名中提取目标编号,用于生成输出文件名。 - 避免全局数据污染:每次处理时复制
sdata副本,防止多次处理后数据叠加。
完整修正代码
library(cruts) library(raster) library(sf) library(rgdal) library(terra) # 定义固定路径 input_dir <- "G:/Mon Drive/Doctorat/Données/Donnée spatiale indonésie/CHIRPS brut" output_dir <- "G:/Mon Drive/Doctorat/Données/Donnée spatiale indonésie/CHIRPS moyenne" shapefile_path <- "G:/Mon Drive/Doctorat/Données/Donnée spatiale indonésie/sub_pro_indon" # 创建输出目录(不存在则自动生成) if (!dir.exists(output_dir)) { dir.create(output_dir, recursive = TRUE) } # 仅读取一次矢量数据,提升效率 sdata <- readOGR(shapefile_path, "sub_pro_indon") # 获取所有.bil文件(带完整路径) files <- list.files(input_dir, pattern = "\\.bil$", full.names = TRUE) # 定义自动化处理函数 mean_calc <- function(file_path) { # 从文件名提取编号(适配chirps-v2.0_201410.bil格式) file_name <- basename(file_path) file_id <- gsub("^chirps-v2\\.0_(\\d+)\\.bil$", "\\1", file_name) output_prefix <- paste0(file_id, "pre_mean") # 读取栅格数据 r <- raster(file_path) # 复制矢量数据副本,避免修改原数据 sdata_copy <- sdata r.vals <- extract(r, sdata_copy) # 处理NA值,确保均值计算有效 r.mean <- unlist(lapply(r.vals, FUN = function(x) mean(x, na.rm = TRUE))) sdata_copy@data <- data.frame(sdata_copy@data, mean = r.mean) # 构建输出文件路径 shp_output <- file.path(output_dir, paste0(output_prefix, ".shp")) csv_output <- file.path(output_dir, paste0(output_prefix, ".csv")) # 写入结果 writeOGR(sdata_copy, output_dir, output_prefix, driver = "ESRI Shapefile") write.csv2(sdata_copy, csv_output, row.names = FALSE) # 打印处理进度(可选) cat(paste("处理完成:", file_name, "\n")) } # 批量处理所有.bil文件 lapply(files, mean_calc)
关键细节说明
- 正则表达式适配:如果
.bil文件名格式变化,需调整gsub中的正则表达式。例如文件名是chirps_201410_v2.bil,正则要改为^chirps_(\\d+)_v2\\.bil$。 - 路径兼容性:用
file.path构建路径,自动适配不同操作系统的路径分隔符,避免手动拼接出错。 - NA值处理:添加
na.rm=TRUE防止栅格中存在NA导致均值计算失败。 - 效率优化:矢量数据仅读取一次,每次处理用副本,减少重复IO操作。
内容的提问来源于stack exchange,提问作者Eliot Wendling
相关产品推荐
相关产品推荐

