R 将多个文件合并为 1 个数据框并保留所有值

R merge multiple files into 1 dataframe and keep all values

我有 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) 组合在一列中..

这是使用来自 data.table

的 rbindlist 和 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>

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

另一个解决方案purrr::map

files <- list.files("/path/",full.names = TRUE)

combinedDF <- files %>% map(read.csv, stringsAsFactors=FALSE, col.names=files) %>% 
  reduce(cbind)

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

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()

这是您的函数的另一个版本,可提供您要求的输出...

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)
}