You need to enable JavaScript to run this app.
最新活动
大模型
产品
解决方案
定价
生态与合作
支持与服务
开发者
了解我们

R语言实现多工作簿指定工作表合并及文件名年份提取

解决你的两个R语言问题:合并Excel工作表与年份提取

嘿,我来帮你搞定这两个问题!先从合并Excel工作表的问题说起,然后再处理年份正则提取的事儿。

一、合并多Excel文件的指定工作表

你的代码目前只拿到一个工作表的数据,主要有几个小问题:

  • 初始化的data.1带NA空行,而且每次循环都把新数据和这个空行绑定,还会覆盖之前的合并结果
  • 没有正确获取工作表名称,sheet.names[j]会出错
  • 没有累积合并数据,每次循环都重置data_merge

下面是修正后的代码,我加了详细注释:

library(XLConnect)

# 设置Excel文件所在的文件夹路径
file_path <- "C:/Users/kushaa/Documents/Frost_casestudy/"
# 只读取.xlsx和.xls文件,同时获取完整文件路径(避免加载工作簿时出错)
files <- list.files(path = file_path, pattern = "\\.xlsx$|\\.xls$", full.names = TRUE)

# 指定要读取的工作表索引
sheet.index <- c(3,6,9)
# 定义最终数据框的列名
colname <- c("Country","Jan","Feb","Mar","Apr","May","Jun","Jul","Aug","Sep","Oct","Nov","Dec","FY","truck_type")

# 初始化一个空的数据框,用来存放合并后的结果
data_merge <- data.frame(matrix(ncol = length(colname), nrow = 0))
names(data_merge) <- colname

# 遍历每个Excel文件
for (i in seq_along(files)){
  # 加载当前工作簿
  wb <- loadWorkbook(files[i])
  # 获取当前工作簿的所有工作表名称
  sheet_names <- getSheets(wb)
  
  # 遍历指定的工作表索引
  for (j in seq_along(sheet.index)){
    # 读取第j个指定的工作表,从第5行开始,无表头
    ss <- readWorksheet(wb, sheet = sheet.index[j], startRow = 5, header = FALSE)
    # 把当前工作表名称作为truck_type,重复对应行数
    truck_type <- rep(sheet_names[sheet.index[j]], nrow(ss))
    # 组合数据并设置列名
    df <- cbind(ss, truck_type)
    names(df) <- colname
    # 将当前工作表的数据追加到合并数据框中
    data_merge <- rbind(data_merge, df)
  }
}

# 移除可能存在的空行(比如工作表末尾的空白行)
data_merge <- data_merge[complete.cases(data_merge$Country), ]

这样修改后,就能把所有指定的工作表数据都合并到一个dataframe里,而且truck_type也能正确对应LCV、HCV这些工作表名称啦。

二、正则提取正确的年份

你当前的正则会匹配从第一个数字到最后一个数字的所有内容,所以拿到的是长串数字。我们需要的是每个文件名里最后出现的四位年份数字,可以用Perl风格的正则来实现:

# 提取每个文件名中最后出现的四位数字(即目标年份)
years <- regmatches(files, regexpr("[0-9]{4}(?!.*[0-9]{4})", files, perl = TRUE))
years

运行后就能得到你想要的结果:

[1] "2014" "2012" "2013"

正则解释:

  • [0-9]{4}:匹配连续的四位数字
  • (?!.*[0-9]{4}):正向否定预查,确保这个四位数字后面没有其他四位数字(也就是找到最后一个四位数字)
  • perl = TRUE:启用Perl风格正则,支持预查语法

如果你的文件名里的目标年份都是跟在_vo_by前面,也可以用更精准的正则:

years <- regmatches(files, regexpr("([0-9]{4})(?=_vo|_by)", files, perl = TRUE))

这个也能得到同样的结果,你可以根据自己所有文件名的规律选择合适的正则。

内容的提问来源于stack exchange,提问作者sree

火山引擎 最新活动