我有很多帧,其中的一些ID或列名是相同的。我想将所有数据帧合并到一个数据帧中,但仅限于所有数据帧中存在的样本。换句话说,我希望新数据帧中的样本交集。例如,第一个数据框(df1)看起来像
m1 m2 m3
P001 60.00 2.0 1
P002 14.30 2.077 1
P003 29.60 2.077 1.4
P004 10.30 2.077 1.3
P005 79.30 2.077 3.1
P006 79.30 2.077 3.1
P008 9.16 2.077 2.2
,第二个数据框(df2)看起来像
patid n1 n2 n3
P001 12.00 2.0 1
P003 17.60 1.7 1
P005 22.30 2.7 1
P006 26.30 1.7 1
同样是第三个数据框
patid k2 k3 k4
P001 8.00 2.0 1.7
P004 9.60 1.7 1.8
P005 7.30 2.7 2.1
P008 6.30 1.7 1.9
P008 6.38 1.78 1.92
我希望第四个数据帧与该数据帧中的所有样本相交。该数据帧中该数据帧中的样本将用于例如P001和P005。
答案可能是这样的
m1 m2 m3 n1 n2 n3 k2 k3 k4
P001 60.00 2.0 1 12.00 2.0 1 8.00 2.0 1.7
P005 79.30 2.077 3.1 22.30 2.7 1 7.30 2.7 2.1
更长的选择是使用循环。嵌套匹配,例如
matchmicSer <- df2[match(rownames(df1), df2$patid)]
matchserMic <- df1[match(df2$patid,rownames(df1))]
并继续,但我相信R应该有一个捷径。合并不是一种选择,因为第二和第三个数据帧中的一些变量可能有重复,如thrid数据帧中的P008。
答案 0 :(得分:4)
根据显示的示例,第一个数据集(&#39; df1&#39;)没有'patid&#39;柱。因此,从&#39; rownames&#39;创建了列。
df1$patid <- row.names(df1)
我们可以在将数据集放入&#39;列表后将Reduce
与merge
一起使用。 (mget(paste0('df', 1:3))
Reduce(function(...) merge(..., by='patid'), mget(paste0('df', 1:3)))
# patid m1 m2 m3 n1 n2 n3 k2 k3 k4
#1 P001 60.0 2.000 1.0 12.0 2.0 1 8.0 2.0 1.7
#2 P005 79.3 2.077 3.1 22.3 2.7 1 7.3 2.7 2.1
关于重复的patid
,在&#39; df3&#39;中,有一个副本(&#39; P008&#39;),但它并不存在于所有数据集中(所以没有在输出中找到)。假设,如果我们有一个&#39; patid&#39;它存在于所有数据集中,并在其中一个数据集中重复
df3$patid[2] <- 'P001'
Reduce(function(...) merge(..., by='patid'), mget(paste0('df', 1:3)))
# patid m1 m2 m3 n1 n2 n3 k2 k3 k4
#1 P001 60.0 2.000 1.0 12.0 2.0 1 8.0 2.0 1.7
#2 P001 60.0 2.000 1.0 12.0 2.0 1 9.6 1.7 1.8
#3 P005 79.3 2.077 3.1 22.3 2.7 1 7.3 2.7 2.1
df1 <- structure(list(m1 = c(60, 14.3, 29.6, 10.3, 79.3, 79.3, 9.16),
m2 = c(2, 2.077, 2.077, 2.077, 2.077, 2.077, 2.077), m3 = c(1,
1, 1.4, 1.3, 3.1, 3.1, 2.2)), .Names = c("m1", "m2", "m3"
), class = "data.frame", row.names = c("P001", "P002", "P003",
"P004", "P005", "P006", "P008"))
df2 <- structure(list(patid = c("P001", "P003", "P005", "P006"),
n1 = c(12, 17.6, 22.3, 26.3), n2 = c(2, 1.7, 2.7, 1.7), n3 = c(1L,
1L, 1L, 1L)), .Names = c("patid", "n1", "n2", "n3"),
class = "data.frame", row.names = c(NA, -4L))
df3 <- structure(list(patid = c("P001", "P004", "P005", "P008",
"P008"), k2 = c(8, 9.6, 7.3, 6.3, 6.38), k3 = c(2, 1.7, 2.7, 1.7,
1.78), k4 = c(1.7, 1.8, 2.1, 1.9, 1.92)), .Names = c("patid", "k2",
"k3", "k4"), class = "data.frame", row.names = c(NA, -5L))
答案 1 :(得分:2)
我已经开始执行批量加入的功能来解决您的问题。
使用akrun生成的数据:
library(data.table) # devtools::install_github("Rdatatable/data.table")
dt1 <- as.data.table(df1, keep.rownames = "patid")
dt2 <- as.data.table(df2)
dt3 <- as.data.table(df3)
library(dwtools) # devtools::install_github("jangorecki/dwtools")
joinbyv(dt3, list(dt2, dt1), by = list("patid","patid"), nomatch = list(0L,0L))
# patid m1 m2 m3 n1 n2 n3 k2 k3 k4
# 1: P001 60.0 2.000 1.0 12.0 2.0 1 8.0 2.0 1.7
# 2: P005 79.3 2.077 3.1 22.3 2.7 1 7.3 2.7 2.1
当然,如果您不想在代码中使用新的依赖项(dwtools),则可以将简单joinbyv
函数定义为:
joinbyv <- function(master, join, by, nomatch){
joinby <- function(master, join, by, nomatch){
setkeyv(join,by)
if(!identical(key(master),key(join))) setkeyv(master,key(join))
join[master, nomatch = nomatch]
}
for(i in 1:length(join)){
master <- joinby(master = master, join[[i]], by[[i]], nomatch[[i]])
}
master
}
答案 2 :(得分:0)
我假设您希望保留在某些表格中重复的共享ID的所有观察结果。
我写在data.table
:
library(data.table) #1.9.5+
setDT(df1,keep.rownames="patid",key="patid")
setDT(df2,key="patid")
setDT(df3,key="patid")
df4<-df1[df2][df3,nomatch=0L]