基于一列将多个 two-column 个文本文件合并到一个数据框中
Merging multiple two-column text files into one data frame based on one column
这个问题是 follow-up 到 this one 的问题,得到了否定的回答,没有答案。所以,我正在尝试使用 R.
我有很多(超过 30 个)这样的文件:
文件 1
5 A1
23 A3
1 B2
289 BX5
90 D3
文件2
2 A1
10 A2
3 B1
1 BX4
90 D3
24 E0
文件 3
4 A0
11 A2
1 B1
2 D3
我想将所有这些组合起来生成这样的数据框:
A0 0 0 4
A1 5 2 0
A2 0 10 11
A3 23 0 0
B1 0 3 1
B2 1 0 0
BX4 0 1 0
BX5 289 0 0
D3 90 90 2
E0 0 24 0
基于this,我尝试使用read.table读取两个文件,同时将第二列指定为行名,然后按行名合并数据框,如下所示:
> df1 <- read.table("File1", row.names = 2)
> df1
V1
A1 5
A3 23
B2 1
BX5 289
D3 90
> df2 <- read.table("File2", row.names = 2)
> df2
V1
A1 2
A2 10
B1 3
BX4 1
D3 90
E0 24
> m1 <- merge(df1, df2, by=0, all=TRUE)
> m1[is.na(m1)] <- 0
> m1
Row.names V1.x V1.y
1 A1 5 2
2 A2 0 10
3 A3 23 0
4 B1 0 3
5 B2 1 0
6 BX4 0 1
7 BX5 289 0
8 D3 90 90
9 E0 0 24
到目前为止一切顺利,但是当我尝试将生成的数据框合并到第三个数据框时,它并没有像我希望的那样工作。因此,我不确定如何继续将所有 30 多个文件合并到一个数据框中。以前我以为我会修改here描述的multmerge
函数,但现在我卡住了。
那么,有人可以帮我解决这个问题吗?提前致谢。
编辑:如果有人能为这个问题建议一个更好的标题,我将不胜感激。
我已尝试针对您的问题调整 multmerge 函数中的 Reduce-part。
#read in the data (can be replaced with filenames
#like f1 <- read.table(file, header=F)
#or even lapply(list.files(mypath), read.table, header=F)
#to get all dataframes in a list
f1 <- read.table(text="5 A1
23 A3
1 B2
289 BX5
90 D3", header=F)
f2 <- read.table(text="2 A1
10 A2
3 B1
1 BX4
90 D3
24 E0", header=F)
f3 <- read.table(text="4 A0
11 A2
1 B1
2 D3", header=F)
#put files in list
myfiles <- list(f1,f2,f3)
#changing colnames because I like keeping my data in order/knowing where it came from.
myfiles <- lapply(1:length(myfiles),function(x){
r <- myfiles[[x]]
colnames(r) <- c(paste0("f",x),"ID")
r
})
#using the Reduce-function
res <- Reduce(function(x,y) {merge(x,y,all=T, by="ID")}, myfiles)
res[is.na(res)]<-0
res
> res
ID f1 f2 f3
1 A1 5 2 0
2 A3 23 0 0
3 B2 1 0 0
4 BX5 289 0 0
5 D3 90 90 2
6 A2 0 10 11
7 B1 0 3 1
8 BX4 0 1 0
9 E0 0 24 0
10 A0 0 0 4
这里是 dplyr
的操作方法。首先,您需要在不分配行名称的情况下加载数据。下面,我重用了您的 file1、file2、file3 结构,但您也可以像阅读 df1、df2、df3 一样以正确的格式阅读它们。您需要一个名称列才能加入。然后你连续做两个full_join
。然后我对数据进行排序并将 NA 更改为 0.
file1 <-data.frame(Names=rownames(file1),V1=file1,row.names = NULL)
file2 <-data.frame(Names=rownames(file2),V1=file2,row.names = NULL)
file3 <-data.frame(Names=rownames(file3),V1=file3,row.names = NULL)
library(dplyr)
out <-file1 %>%
full_join(file2,by = "Names") %>%
full_join(file3,by = "Names") %>%
arrange(Names)
out[is.na(out)]<-0
#> out
# Names V1.x V1.y V1
#1 A0 0 0 4
#2 A1 5 2 0
#3 A2 0 10 11
#4 A3 23 0 0
#5 B1 0 3 1
#6 B2 1 0 0
#7 BX4 0 1 0
#8 BX5 289 0 0
#9 D3 90 90 2
#10 E0 0 24 0
更新
要处理任意数量的文件,我们必须引入一个循环。
myfiles <- list(file1,file2,file3)
out <-file1 #first file
for (i in myfiles[-1]){ #all but first file
out <-full_join(out,i,by = "Names")
}
out <-arrange(out,Names)
out[is.na(out)]<-0
out
> out
Names V1.x V1.y V1
1 A0 0 0 4
2 A1 5 2 0
3 A2 0 10 11
4 A3 23 0 0
5 B1 0 3 1
6 B2 1 0 0
7 BX4 0 1 0
8 BX5 289 0 0
9 D3 90 90 2
10 E0 0 24 0
这个问题是 follow-up 到 this one 的问题,得到了否定的回答,没有答案。所以,我正在尝试使用 R.
我有很多(超过 30 个)这样的文件:
文件 1
5 A1 23 A3 1 B2 289 BX5 90 D3
文件2
2 A1 10 A2 3 B1 1 BX4 90 D3 24 E0
文件 3
4 A0 11 A2 1 B1 2 D3
我想将所有这些组合起来生成这样的数据框:
A0 0 0 4
A1 5 2 0
A2 0 10 11
A3 23 0 0
B1 0 3 1
B2 1 0 0
BX4 0 1 0
BX5 289 0 0
D3 90 90 2
E0 0 24 0
基于this,我尝试使用read.table读取两个文件,同时将第二列指定为行名,然后按行名合并数据框,如下所示:
> df1 <- read.table("File1", row.names = 2)
> df1
V1
A1 5
A3 23
B2 1
BX5 289
D3 90
> df2 <- read.table("File2", row.names = 2)
> df2
V1
A1 2
A2 10
B1 3
BX4 1
D3 90
E0 24
> m1 <- merge(df1, df2, by=0, all=TRUE)
> m1[is.na(m1)] <- 0
> m1
Row.names V1.x V1.y
1 A1 5 2
2 A2 0 10
3 A3 23 0
4 B1 0 3
5 B2 1 0
6 BX4 0 1
7 BX5 289 0
8 D3 90 90
9 E0 0 24
到目前为止一切顺利,但是当我尝试将生成的数据框合并到第三个数据框时,它并没有像我希望的那样工作。因此,我不确定如何继续将所有 30 多个文件合并到一个数据框中。以前我以为我会修改here描述的multmerge
函数,但现在我卡住了。
那么,有人可以帮我解决这个问题吗?提前致谢。
编辑:如果有人能为这个问题建议一个更好的标题,我将不胜感激。
我已尝试针对您的问题调整 multmerge 函数中的 Reduce-part。
#read in the data (can be replaced with filenames
#like f1 <- read.table(file, header=F)
#or even lapply(list.files(mypath), read.table, header=F)
#to get all dataframes in a list
f1 <- read.table(text="5 A1
23 A3
1 B2
289 BX5
90 D3", header=F)
f2 <- read.table(text="2 A1
10 A2
3 B1
1 BX4
90 D3
24 E0", header=F)
f3 <- read.table(text="4 A0
11 A2
1 B1
2 D3", header=F)
#put files in list
myfiles <- list(f1,f2,f3)
#changing colnames because I like keeping my data in order/knowing where it came from.
myfiles <- lapply(1:length(myfiles),function(x){
r <- myfiles[[x]]
colnames(r) <- c(paste0("f",x),"ID")
r
})
#using the Reduce-function
res <- Reduce(function(x,y) {merge(x,y,all=T, by="ID")}, myfiles)
res[is.na(res)]<-0
res
> res
ID f1 f2 f3
1 A1 5 2 0
2 A3 23 0 0
3 B2 1 0 0
4 BX5 289 0 0
5 D3 90 90 2
6 A2 0 10 11
7 B1 0 3 1
8 BX4 0 1 0
9 E0 0 24 0
10 A0 0 0 4
这里是 dplyr
的操作方法。首先,您需要在不分配行名称的情况下加载数据。下面,我重用了您的 file1、file2、file3 结构,但您也可以像阅读 df1、df2、df3 一样以正确的格式阅读它们。您需要一个名称列才能加入。然后你连续做两个full_join
。然后我对数据进行排序并将 NA 更改为 0.
file1 <-data.frame(Names=rownames(file1),V1=file1,row.names = NULL)
file2 <-data.frame(Names=rownames(file2),V1=file2,row.names = NULL)
file3 <-data.frame(Names=rownames(file3),V1=file3,row.names = NULL)
library(dplyr)
out <-file1 %>%
full_join(file2,by = "Names") %>%
full_join(file3,by = "Names") %>%
arrange(Names)
out[is.na(out)]<-0
#> out
# Names V1.x V1.y V1
#1 A0 0 0 4
#2 A1 5 2 0
#3 A2 0 10 11
#4 A3 23 0 0
#5 B1 0 3 1
#6 B2 1 0 0
#7 BX4 0 1 0
#8 BX5 289 0 0
#9 D3 90 90 2
#10 E0 0 24 0
更新
要处理任意数量的文件,我们必须引入一个循环。
myfiles <- list(file1,file2,file3)
out <-file1 #first file
for (i in myfiles[-1]){ #all but first file
out <-full_join(out,i,by = "Names")
}
out <-arrange(out,Names)
out[is.na(out)]<-0
out
> out
Names V1.x V1.y V1
1 A0 0 0 4
2 A1 5 2 0
3 A2 0 10 11
4 A3 23 0 0
5 B1 0 3 1
6 B2 1 0 0
7 BX4 0 1 0
8 BX5 289 0 0
9 D3 90 90 2
10 E0 0 24 0