【问题标题】:R merge multiple files into 1 dataframe and keep all valuesR将多个文件合并到1个数据框中并保留所有值
【发布时间】:2017-07-07 15:42:58
【问题描述】:

我有 6 个多个文件,每个文件只有 1 列名称。我想读取所有这些文件并将它们组合在 1 个数据框中,使其看起来像这样:

file1  file2  file3  file4  file5  file6
adam   adam   adam   adam   adam   adam
Roy    NA     Roy    Roy    NA     NA
NA     Sam    Sam    NA     NA     NA

结果数据框的colnames 应该代表实际的文件名。假设我读取的文件名为file1.txtfile2.txt 等等..

任何帮助将不胜感激。

到目前为止我一直在尝试什么:

multmerge = function(mypath){
+ filenames=list.files(path=mypath, full.names=TRUE, pattern = "\\.txt$")
+ datalist = lapply(filenames, function(x){read.csv(file=x,header=F)})
+ Reduce(function(x,y) {merge(x,y, all.x=T)}, datalist)}
> mymergeddata = multmerge("/Path/To/The/Folder/Having/All/Files")
> dim(mymergeddata)
[1] 11508     1

如此处所示,它将所有值 (names) 组合在一列中..

【问题讨论】:

  • 而不是Reduce 行,试试do.call(cbind,datalist)
  • @AndrewGustar data.frame 中的错误(...,check.names = FALSE):参数暗示不同的行数:11508、10307、9917、9798、12167

标签: r merge semi-join


【解决方案1】:

这是使用 rbindlist 和 data.table 中的 dcast 的一种方法

library(data.table)
file_list <- list.files("c:/temp/files/",full.names = TRUE)
import_files <- lapply(file_list,read.csv,stringsAsFactors =FALSE)
rbinded_files <- na.omit(rbindlist(import_files,idcol="file"))
dcast(rbinded_files,file1 ~file,fun=max, na.rm=TRUE)

  file1    1    2    3    4    5    6
1  adam adam adam adam adam adam adam
2   Roy  Roy <NA>  Roy  Roy <NA> <NA>
3   Sam <NA>  Sam  Sam <NA> <NA> <NA>

如果需要,您可以删除第一列。

【讨论】:

  • 我尝试了您的解决方案,但 dcast 的最后一行给了我错误:Using 'V1' as value column. Use 'value.var' to override Error in eval(expr, envir, enclos) : object 'file1' not found
  • 这里有一个拼写错误,dcast 将被用作:dcast(rbinded_files, V1 ~ file, fun=max, na.rm=T)
【解决方案2】:

这可能不是最有效的,但该函数应该可以解决问题,我很高兴听到有关改进该函数的方法,因为我是一个堆栈新手:

library(data.table); library(tidyverse)

multmerge <- function(dir) {
    # Load files and bind columns
    full_dir_filenames <- list.files(path = dir, full.names = TRUE, pattern = "\\.txt$")
    datalist <- lapply(full_dir_filenames, read_csv, col_names = FALSE) %>% 
        lapply(t) %>% 
        lapply(as.tibble)
    df <- bind_cols(datalist)

    # Append the column names
    file_names <- list.files(path = dir, full.names = FALSE, pattern = "\\.txt$")
    col_names <- tstrsplit(file_names, split = "[.]")[[1]]
    colnames(df) <- col_names

    df
}

multmerge()

【讨论】:

    【解决方案3】:

    purrr::map 的另一种解决方案

    files <- list.files("/path/",full.names = TRUE)
    
    combinedDF <- files %>% map(read.csv, stringsAsFactors=FALSE, col.names=files) %>% 
      reduce(cbind)
    

    【讨论】:

    • 我收到以下错误:Error in data.frame(..., check.names = FALSE) : arguments imply differing number of rows: 11507, 10306
    • @Newbie Ahh,我忘了 cbind 必须传递具有相同行数的列。要使上述方法起作用,您必须用 NA 填充每一列以匹配最长列的长度。
    【解决方案4】:

    这是你的函数的另一个版本,它给出了你要求的输出......

    multmerge <- function(mypath){
      filenames <- list.files(path=mypath, full.names=TRUE, pattern = "\\.txt$")
      datalist <- lapply(filenames, function(x){
                df <- read.csv(file=x,header=F,stringsAsFactors = FALSE)
                df[,2] <- gsub("\\.txt","",basename(x))
                return(df)})
      namesdf <- do.call(rbind,datalist)
      output <- as.data.frame.matrix(table(namesdf$name,namesdf$file))
      for(j in 1:nrow(output)){
        output[j,] <- ifelse(as.numeric(output[j,])==0,NA,row.names(output)[j])
      }
      return(output)
    }
    

    【讨论】:

    • 感谢您或抽出时间提出解决方案。这个函数只返回这个:data frame with 0 columns and 1 row
    猜你喜欢
    • 1970-01-01
    • 2021-04-11
    • 2022-01-25
    • 2017-06-25
    • 2017-07-11
    • 2015-03-30
    • 2021-09-26
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多