在R中将数据框组合起来,对于相同的列求和

13

我有3个数据框(行:站点,列:物种名称),它们包含了各站点的物种丰度。行数相同,但是列数不同,因为不是所有物种在这三个数据框中都有记录。我想将它们合并成一个数据框,并对相同物种的丰度求和。例如:

data.frame1

       Sp1  Sp2  Sp3  Sp4
site1   1    2    3    1
site2   0    2    0    1
site3   1    1    1    1

数据框2

       Sp1  Sp2  Sp4
 site1  0    1    2
 site2  1    2    0
 site3  1    1    1

数据框3

       Sp1  Sp2  Sp5  Sp6
 site1  0    1    1    1     
 site2  1    1    1    5
 site3  2    0    0    0

我想要的是类似于:

       Sp1  Sp2  Sp3  Sp4  Sp5  Sp6
 site1  1    4    3    3    1    1
 site2  2    5    0    1    1    5
 site3  4    2    1    2    0    0

我想我得使用合并功能,但迄今为止我的尝试都未能获得我想要的结果。

感激任何帮助。


也许 aggregatemerge 更好? - Carl Witthoft
4个回答

23

我会这样使用plyrrbind.fill:

pp <- cbind(names=c(rownames(df1), rownames(df2), rownames(df3)), 
                        rbind.fill(list(df1, df2, df3)))

#   names Sp1 Sp2 Sp3 Sp4 Sp5 Sp6
# 1 site1   1   2   3   1  NA  NA
# 2 site2   0   2   0   1  NA  NA
# 3 site3   1   1   1   1  NA  NA
# 4 site1   0   1  NA   2  NA  NA
# 5 site2   1   2  NA   0  NA  NA
# 6 site3   1   1  NA   1  NA  NA
# 7 site1   0   1  NA  NA   1   1
# 8 site2   1   1  NA  NA   1   5
# 9 site3   2   0  NA  NA   0   0

然后,使用plyrddply进行聚合,如下所示:

ddply(pp, .(names), function(x) colSums(x[,-1], na.rm = TRUE))
#   names Sp1 Sp2 Sp3 Sp4 Sp5 Sp6
# 1 site1   1   4   3   3   1   1
# 2 site2   2   5   0   1   1   5
# 3 site3   4   2   1   2   0   0

3
我有一个解决方案在脑海中,但我保证它不像这样优雅。 +1 - Tyler Rinker
@eugenego 你可以在最佳答案旁边打勾标记。 - Tyler Rinker

7

另一个选择是使用reshape2中的melt/cast。以下是一个简单的示例:

df1 <- read.table(header=T, text="
    Sp1  Sp2  Sp3  Sp4
    site1   1    2    3    1
    site2   0    2    0    1
    site3   1    1    1    1")

df2 <- read.table(header=T, text="
       Sp1  Sp2  Sp4
 site1  0    1    2
 site2  1    2    0
 site3  1    1    1")

df3 <- read.table(header=T, text="
       Sp1  Sp2  Sp5  Sp6
 site1  0    1    1    1     
 site2  1    1    1    5
 site3  2    0    0    0")

df1$site <- rownames(df1)
df2$site <- rownames(df2)
df3$site <- rownames(df3)

DF <- rbind(melt(df1,id="site"),melt(df2,id="site"),melt(df3,id="site"))
dcast(data=DF,formula=site ~ variable,fun.aggregate=sum)

   site Sp1 Sp2 Sp3 Sp4 Sp5 Sp6
1 site1   1   4   3   3   1   1
2 site2   2   5   0   1   1   5
3 site3   4   2   1   2   0   0

简而言之,我们使用站点指定作为附加变量,并将每个数据框转换为长格式,随后将它们连接成一个单独的数据框。后者包含所有长格式中的值。通过 dcast,我们创建您所需的数据框,其中站点位于行中(公式左侧),变量位于列中(公式右侧)。对于产生多个单元格的变量,应用 sum 函数。
当然,可以使用循环或 *apply 函数扩展代码以适用于更一般的情况。

6

除了现有的选项,这里再介绍两个使用基本 R 实现的选项。

第一个选项宽聚合(有点像)

temp <- cbind(df1, df2, df3)
temp
#       Sp1 Sp2 Sp3 Sp4 Sp1 Sp2 Sp4 Sp1 Sp2 Sp5 Sp6
# site1   1   2   3   1   0   1   2   0   1   1   1
# site2   0   2   0   1   1   2   0   1   1   1   5
# site3   1   1   1   1   1   1   1   2   0   0   0
sapply(unique(colnames(temp)), 
       function(x) rowSums(temp[, colnames(temp) == x, drop = FALSE]))
#       Sp1 Sp2 Sp3 Sp4 Sp5 Sp6
# site1   1   4   3   3   1   1
# site2   2   5   0   1   1   5
# site3   4   2   1   2   0   0

第二个选项: 半宽到长,再到宽

从概念上讲,这与 Maxim.K 的答案类似: 将数据转换为长格式,这样操作起来会更加容易:

> temp1 <- t(cbind(df1, df2, df3))
> # You'll get a warning in the next step
> # Safe to ignore though...
> temp2 <- data.frame(var = rownames(temp), stack(data.frame(temp)))
Warning message:
In data.row.names(row.names, rowsi, i) :
  some row.names duplicated: 5,6,7,8,9 --> row.names NOT used
> xtabs(values ~ ind + var, temp2)
       var
ind     Sp1 Sp2 Sp3 Sp4 Sp5 Sp6
  site1   1   4   3   3   1   1
  site2   2   5   0   1   1   5
  site3   4   2   1   2   0   0

我已经使用了“第一选项”,对于一个大小为14500 x 130000的“temp1”数据框,它比提出的答案更完美且更快。 - marb_021

2
创建一个“模板”数组,其中包含您需要的所有列,这是对Arun答案的另一种选择。
Rgames> bbar<-data.frame('one'=rep(0,3),'two'=rep(0,3),'three'=rep(0,3))
Rgames> bbar
  one two three
1  0    0    0
2   0    0    0
3   0    0    0

然后,假设您有类似以下的数据框:
Rgames> bar1<-data.frame('one'=c(1,2,3),'two'=c(4,5,6))
Rgames> bar1
  one two
1   1   4
2   2   5
3   3   6

创建一个扩展的数据框:
Rgames> newbar1<-bbar
Rgames> for (jj in names(bar) )  newbar1[[jj]]<-bar[[jj]]
Rgames> newbar1
  one two three
1   1   4    0
2   2   5    0
3   3   6    0

然后将所有这样扩展的数据框求和。笨拙但简单。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接