【问题标题】:Importing csv files and merging in a loop based on file name in R导入csv文件并根据R中的文件名循环合并
【发布时间】:2017-07-20 14:51:34
【问题描述】:

我有一个大约 75 个 CSV 的文件夹,有些是同一站的 2 个,有些是独立的。

有没有办法遍历文件夹,拉出两个具有相同前 4 个字符的 CSV,然后导出为一个,合并 CSV?在下面的循环中?都是一样的结构。

这里有五个示例文件名(在文件夹“文件夹”中)

> files
"13_2016_01-01~2016-09-30.csv"
"13_2016_10-01~2017-06-30.csv"
"1222_2016_01-01~2016-09-30.csv"
"1222_2016_10-01~2017-06-30.csv"
"1114_2016_01-01~2016-09-30.csv"

这里是目前在每个文件中读取和导出的代码:

z <- NULL
files <- dir("Folder")

for (file in files) {
  x <- read.csv(file.path("Folder", file), as.is=T, skip=12)

write.csv(x, paste(file)), row.names=F, col.names=F)
}

使用这个例子,我想得到这个文件列表:

> files
"13_2016-2017.csv"
"1222_2016-2017.csv"
"1114_2016-2017.csv"

【问题讨论】:

    标签: r csv for-loop


    【解决方案1】:

    考虑一个正则表达式匹配解决方案来遍历文件前缀集以进行读/写 csv 操作:

    # OP's POSTED EXAMPLE
    files <- c("13_2016_01-01~2016-09-30.csv",
               "13_2016_10-01~2017-06-30.csv",
               "1222_2016_01-01~2016-09-30.csv",
               "1222_2016_10-01~2017-06-30.csv",
               "1114_2016_01-01~2016-09-30.csv")
    
    # GENERALIZED FOR ALL CSVs IN WORKING DIR
    # files <- list.files(path="/path/to/csv/folder", pattern="\\.csv")         
    
    m <- regexpr("^.*_", files)    
    file_prefix <- unique(regmatches(files, m))     # VECTOR OF UNIQUE PREFIX MATCHES
    file_prefix
    # [1] "13_2016_"   "1222_2016_" "1114_2016_"
    
    # NAMED LIST OF ROW-BINDED DATAFRAMES
    dfList <- sapply(file_prefix, function(p){
                    dfs <- lapply(list.files(path="/path/to/csv/folder", 
                                             pattern=p, full.names=TRUE), function(f) {
                                  setNames(read.csv(f), c("Col1", "Col2", "Col3"))
                           })                                  
                    do.call(rbind, dfs)   
              }, simplify=FALSE)
    
    # OUTPUT CSV FILES NAMED WITH PREFIX AND '2016-2017' SUFFIX
    out <- mapply(function(d,n) write.csv(d, file=paste0(n,"2016-2017.csv"), row.names=FALSE), 
                  dfList, names(dfList), SIMPLIFY=FALSE)
    

    【讨论】:

    • 感谢您的帮助 - 我在 out 函数期间收到此错误:在文件中(文件,ifelse(附加,“a”,“w”)):无法打开文件 '1041* 2016-2017.csv':参数无效
    • 有趣。为什么星号会通过?这对于 Windows 机器上的文件/目录是无效的字符。您的 file_prefix 矢量输出是什么?您的 dfList 是否包含 dfs?
    • file_prefix 向量输出为:“1041”、“1051”、“109_”等...我再次运行它,现在一切似乎都通过、导出等...没有星号。但是,当我查看 dfList 时,它只有 NULL 值,尽管它列出了我想要的适当文件数……似乎没有提取 CSV 数据
    • 文件名没有下划线?此解决方案希望它像您发布的数据一样。
    • 啊,是的。文件不会完全匹配。它们将匹配前 4 个字符,而不是完整的文件名。所以只有前 4 个字符会从每个名称中提取出来。
    【解决方案2】:

    如果没有您的数据,我无法测试我的代码,因此我会将我的答案更接近于伪代码,但我认为这应该可行:

    library(stringr)
    library(dplyr)
    files <- list.files() #List all the files
    FileGroups <- paste0(unique(str_sub(files,1,4)),"*") #find the file groups and apend a '*' for regex in next code chunk
    
    for (i in 1:length(FileGroups)){
      df <- list.files(pattern=FileGroups[i])%>% # find all files in one group
        lappy(read_csv()) %>% #read in
        bind_rows() #bind together
      write.csv(df,paste0(FileGroups[i],"_2016-2017.csv")) #output
    
    }
    

    您可能需要尝试这个,但想法是首先找到所有不同的模式,然后加载与该模式匹配的所有 csv 并绑定它们。我使用this question 作为行绑定代码。另外,您说的是 4 位代码,但以您的示例为例,您可能有 2 位代码,如果是这种情况,我会使用 str_split 来查找组。希望这有帮助!

    【讨论】:

    • 感谢您的帮助!我喜欢这种方法,感谢您将代码放入循环中。但是,当我运行它时出现错误:read.table 中的错误(file = file,header = header,sep = sep,quote = quote,:'file' must be a string or connection
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2021-10-24
    • 1970-01-01
    • 1970-01-01
    • 2021-05-12
    • 2015-04-14
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多