如何在R语言中按条件将文件读取到两个独立列表的函数实现
实验数据处理需求及解决方法
背景与需求
我正在开展实验,从两个数据源获取数据,date_time为统一匹配变量,两个数据源的文件结构一致(csv或txt格式),仅文件名存在差异。需要完成两个核心操作:
- 将文件按文件名关键词拆分到两个独立列表:一个包含含“solid”的文件,另一个包含含“water”的文件
- 从每个数据框的文件名中拆分出以“_”分隔的新列(如
paint = "epoxy1"、thickness = "10"),方便后续按date_time、paint、thickness做内连接
示例数据
list_of_files <- structure( list ( solid_epoxy1_10 = data.frame( date_time = c("20/07/2022 13:46", "20/07/2022 13:56", "20/07/2022 14:06"), frequency = c("30000", "31000", "32000"), index = c("1", "2", "3") ), solid_otherpaint_20 = data.frame( date_time = c("20/07/2022 13:10", "20/07/2022 13:20", "20/07/2022 14:30"), frequency = c("20000", "21000", "22000"), index = c("1", "2", "3") ), water_epoxy1_10 = data.frame( date_time = c("20/07/2022 13:46", "20/07/2022 13:56", "20/07/2022 14:06"), temperature = c("22.3", "22.6", "22.5") ), water_otherpaint_20 = data.frame( date_time = c("20/07/2022 13:10", "20/07/2022 13:20", "20/07/2022 14:30"), temperature = c("24.5", "24.6", "24.8") ) ) )
当前问题
我编写的load_files函数无法实现需求:
load_files <- function(list_of_files) { all.files.board <- list() all.files.temp <- list() for (i in 1:length(list_of_files)) { if (exists("board")) { all.files.board[[i]] = fread(list_of_files[i]) } else{ all.files.temp[[i]] = fread(list_of_files[i]) } return(list(all.files.board, all.files.temp)) } }
我熟悉tidyverse包,但自定义函数编写经验不足,需要解决思路。
解决思路(基于tidyverse)
1. 拆分文件到两个列表
无需循环,直接通过列表名称筛选即可:
# 提取含solid的文件列表 solid_list <- list_of_files[grepl("solid", names(list_of_files))] # 提取含water的文件列表 water_list <- list_of_files[grepl("water", names(list_of_files))]
2. 从文件名拆分新增列
用purrr::imap遍历列表(同时获取文件名和对应数据框),再通过tidyr::separate_wider_delim拆分文件名:
library(tidyverse) # 处理solid列表,新增paint和thickness列 solid_processed <- imap(solid_list, function(df, filename) { # 去掉前缀"solid_"后,按_拆分文件名 filename %>% str_remove("^solid_") %>% separate_wider_delim(delim = "_", names = c("paint", "thickness")) %>% bind_cols(df, .) }) # 处理water列表同理 water_processed <- imap(water_list, function(df, filename) { filename %>% str_remove("^water_") %>% separate_wider_delim(delim = "_", names = c("paint", "thickness")) %>% bind_cols(df, .) })
3. 合并两个数据源(内连接)
将处理后的列表合并为单个数据框,再按指定字段做内连接:
# 合并solid列表为单数据框 solid_df <- bind_rows(solid_processed) # 合并water列表为单数据框 water_df <- bind_rows(water_processed) # 按date_time、paint、thickness内连接 combined_df <- inner_join(solid_df, water_df, by = c("date_time", "paint", "thickness"))
完整函数封装(可选)
如果需要封装成复用函数,结合tidyverse写法更简洁:
process_data <- function(file_list) { # 拆分列表 solid_list <- file_list[grepl("solid", names(file_list))] water_list <- file_list[grepl("water", names(file_list))] # 处理solid数据并合并 solid_processed <- imap(solid_list, ~{ .y %>% str_remove("^solid_") %>% separate_wider_delim("_", c("paint", "thickness")) %>% bind_cols(.x, .) }) %>% bind_rows() # 处理water数据并合并 water_processed <- imap(water_list, ~{ .y %>% str_remove("^water_") %>% separate_wider_delim("_", c("paint", "thickness")) %>% bind_cols(.x, .) }) %>% bind_rows() # 返回内连接结果 inner_join(solid_processed, water_processed, by = c("date_time", "paint", "thickness")) } # 调用函数 result <- process_data(list_of_files)
原函数问题分析
exists("board")逻辑错误:该语句是检查当前环境是否存在名为board的对象,和文件名关键词无关return放在循环内部:第一次循环就直接返回结果,无法遍历所有文件- 缺少文件名拆分的核心逻辑
内容的提问来源于stack exchange,提问作者Silvia
相关产品推荐
相关产品推荐

