我有 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.txt
、file2.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
(组合在一列中。
这是使用rbindlist 和 dcast 从 data.table 执行此操作的一种方法
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>
如果需要,可以删除第一列。
这可能不是最有效的,但函数应该可以解决问题,我很高兴听到改进函数的方法,因为我是堆栈新手:
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()
另一种purrr::map
解决方案
files <- list.files("/path/",full.names = TRUE)
combinedDF <- files %>% map(read.csv, stringsAsFactors=FALSE, col.names=files) %>%
reduce(cbind)
这是函数的另一个版本,它给出了你要求的输出......
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)
}