You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何在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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.17 16:35:26