R语言循环处理时序文件:添加文件名列及代码问题排查
时序数据读取与处理代码排查
我有时序数据存储在月度文件夹下的日分子文件夹的txt文件中,已经通过R代码读取子文件夹下的txt文件并过滤掉无需分析的文件,但尝试循环读取文件(跳过14行)并添加文件名等列时未得到预期结果,请求排查代码缺失部分。
原代码
setwd(".../2018/Jan") parent.folder <-".../2018/Jan" sub.folders <- list.dirs(parent.folder, recursive=TRUE)[-1] #To read the sub-folders under parent folder r.scripts <- file.path(sub.folders) A_2018 <- list() for (j in seq_along(r.scripts)) { A_2018[[j]] <- dir(r.scripts[j],"\\.txt$")}
trim_to_two <- function(x) { runs = rle(gsub("^L1_\\d{4}_\\d{4}_","",x)) return(cumsum(runs$lengths)[which(runs$lengths > 2)] * -1) } A_2018_new <- list() for (j in seq_along(A_2018)) { A_2018_new[[j]] <- A_2018[[j]][trim_to_two(A_2018[[j]])] }
for (i in 1:length(A_2018_new)) { for (j in 1:length(A_2018_new[[i]])){ filename <- paste(str_sub(A_2018_new[[i]][j], 1, 14)) assign(filename, read_tsv(complete_file_name, skip = 14, col_names = FALSE), ) Y <- r.scripts %>% str_sub(46, 49) MD <- r.scripts %>% str_sub(58, 61) HM <- filename %>% str_sub(9, 12) Turn <- filename %>% str_sub(14, 14) time_minute <- paste(Y, MD, HM, sep="-") Map(cbind, filename, SampleID = names(filename)) } }
代码问题排查与修正
- 缺失文件完整路径变量:读取文件时使用的
complete_file_name未定义,需要拼接子文件夹路径和当前文件名,否则R找不到要读取的文件。 assign未处理附加列:用assign创建的变量只是原始读取的数据,没有把Y、MD等附加信息合并进去,需要先读取数据到临时对象,再合并列后保存。- 硬编码路径索引易出错:
str_sub(46,49)这类硬编码的索引是针对特定路径长度的,换个路径就会失效,应该从子文件夹名称提取日期信息,比如用basename()获取子文件夹名后再分割。 Map(cbind)用法错误:这里的Map没有作用到实际读取的数据上,也没有保存结果,应该直接对数据框执行cbind或mutate操作。- 零散变量不利于后续分析:用
assign创建大量独立变量会导致环境混乱,推荐用列表统一存储所有处理后的数据,最后可合并为一个大的数据框。
修正后的代码示例
library(tidyverse) # 设置根路径 parent.folder <- ".../2018/Jan" setwd(parent.folder) # 获取所有日分子文件夹 sub.folders <- list.dirs(parent.folder, recursive = TRUE)[-1] # 读取每个子文件夹下的txt文件列表 A_2018 <- map(sub.folders, ~ dir(.x, "\\.txt$")) # 过滤文件的函数(调整索引逻辑,确保保留正确的文件) trim_to_two <- function(x) { runs <- rle(gsub("^L1_\\d{4}_\\d{4}_","",x)) # 标记需要剔除的索引,返回保留的索引 exclude_indices <- cumsum(runs$lengths)[which(runs$lengths > 2)] keep_indices <- which(!seq_along(x) %in% exclude_indices) return(keep_indices) } # 应用过滤函数,得到待处理的文件列表 A_2018_new <- map(A_2018, ~ .x[trim_to_two(.x)]) # 初始化列表存储处理后的数据 processed_data <- list() current_idx <- 1 # 循环处理每个子文件夹下的文件 for (i in seq_along(A_2018_new)) { current_subfolder <- sub.folders[i] # 从子文件夹名提取年月日(假设子文件夹名为"20180101"格式,可根据实际调整) folder_date <- basename(current_subfolder) year <- str_sub(folder_date, 1, 4) month_day <- str_sub(folder_date, 5, 8) # 处理当前子文件夹下的每个文件 for (j in seq_along(A_2018_new[[i]])) { current_file <- A_2018_new[[i]][j] # 拼接文件完整路径 file_full_path <- file.path(current_subfolder, current_file) # 读取文件,跳过前14行 raw_data <- read_tsv(file_full_path, skip = 14, col_names = FALSE) # 从文件名提取信息 filename_prefix <- str_sub(current_file, 1, 14) hour_minute <- str_sub(filename_prefix, 9, 12) turn <- str_sub(filename_prefix, 14, 14) time_minute <- paste(year, month_day, hour_minute, sep = "-") # 添加附加列到数据中 processed_df <- raw_data %>% mutate( filename = current_file, SampleID = filename_prefix, year = year, month_day = month_day, hour_minute = hour_minute, turn = turn, time_minute = time_minute ) # 将处理好的数据存入列表 processed_data[[current_idx]] <- processed_df current_idx <- current_idx + 1 } } # 可选:合并所有数据为一个大的数据框,方便后续分析 all_timedata <- bind_rows(processed_data)
内容的提问来源于stack exchange,提问作者Heiwa
相关产品推荐
相关产品推荐

