利用文件名子串在数据框列表中创建新变量
批量读取RDS文件并添加来源日期列解决方案
问题背景
有一批存储数据框的.rds文件,文件名列表如下:
files <- c("file_2022-11-30.rds", "file_2022-12-01.rds")
需要实现:
- 将每个文件读取为数据框列表
- 给每个数据框添加
date列,值为对应文件名中的日期部分 - 最终合并为一个完整的数据框
用户尝试用lapply实现但写法无效,原代码如下:
library(dplyr) df_list <- lapply(files, readRDS) %>% lapply(FUN = function(x) mutate(date = as.Date(stringr::str_sub(files[x], start = -14, end = -5)))) %>% bind_rows()
期望输出:
var1 date 1 1 2022-11-30 2 2 2022-11-30 3 2 2022-11-30 4 1 2022-11-30 5 2 2022-11-30 6 2 2022-12-01 7 1 2022-12-01 8 2 2022-12-01 9 1 2022-12-01 10 2 2022-12-01
错误原因
原代码的核心问题是:第二个lapply中的参数x是读取后的 data.frame 对象,并非文件名列表的索引,因此files[x]的写法逻辑错误,无法正确提取对应文件名。
简洁解决方案
方案1:带索引的lapply遍历
直接遍历文件名的索引,同时获取文件名和对应的数据框:
library(dplyr) library(stringr) df_combined <- lapply(seq_along(files), function(i) { # 读取当前文件 current_df <- readRDS(files[i]) # 提取日期并添加列 current_df %>% mutate(date = as.Date(str_sub(files[i], start = -14, end = -5))) }) %>% bind_rows()
方案2:用Map函数配对处理
Map可以同时平行遍历文件名和数据框列表,实现一一配对处理:
library(dplyr) library(stringr) # 先批量读取所有文件 df_list <- lapply(files, readRDS) # 配对文件名与数据框,添加日期列 df_combined <- Map(function(df, filename) { df %>% mutate(date = as.Date(str_sub(filename, -14, -5))) }, df_list, files) %>% bind_rows()
方案3:tidyverse风格的purrr::map2
如果习惯tidyverse工具链,map2可以更简洁地处理两个平行向量的配对操作:
library(tidyverse) df_combined <- map2(files, map(files, readRDS), function(filename, df) { df %>% mutate(date = as.Date(str_sub(filename, -14, -5))) }) %>% bind_rows() # 更简洁的公式写法 df_combined <- map2(files, map(files, readRDS), ~ .y %>% mutate(date = as.Date(str_sub(.x, -14, -5)))) %>% bind_rows()
内容的提问来源于stack exchange,提问作者James Martherus
相关产品推荐
相关产品推荐

