如何在R

时间:2016-01-26 05:51:58

标签: r merge dataframe rbind

我有20多个data.frames,列数相同但行数不同。我的目标是将data.frames合并为" Name" (这是一个包含五个名称的列表)并且在合并时我希望具有相同名称的行对A列求和,对B列求和,并得到C列的平均值。

这是我目前正在做的事情。

首先,我将一次合并2个data.frames。

DF <- merge(x=abc, y=def, by = "Name", all = T)

合并DF看起来像这样

Name                              A.x    B.x   C.x   A.y   B.y  C.y
name1,name2,name3,name4,name5      11     24     7    NA    NA   NA
name1,name3,name4,name6,name7       4      8    12     3     4    7
name1,name2,name5,name6,name7      12      4     5    NA    NA   NA
name3,name4,name5,name6,name7      NA     NA    NA    15     3   28

然后,我将添加这些ifelse语句来处理NAs和非唯一行。对于非唯一行,它将为A添加B和C,它将获得平均值。

DF$A <- ifelse(is.na(DF$A.x), DF$A.y,
    ifelse(is.na(DF$A.y), DF$A.x,
        ifelse((!is.na(DF$A.x)) & (!is.na(DF$A.y)), DF$A.x + DF$A.y, 1)))
DF$B <- ifelse(is.na(DF$B.x), DF$B.y, 
    ifelse(is.na(DF$B.y), DF$B.x,
        ifelse((!is.na(DF$B.x)) & (!is.na(DF$B.y)), DF$B.x + DF$B.y, 1)))
DF$C <- ifelse(is.na(DF$C.x), DF$C.y, 
    ifelse(is.na(DF$C.y), DF$C.x,
        ifelse((!is.na(DF$C.x)) & (!is.na(DF$C.y)), (DF$C.x  + DF$C.y)/2, 1)))

DF现在看起来像这样

Name                            A.x  B.x  C.x  A.y  B.y  C.y   A   B   C   
name1,name2,name3,name4,name5    11   24    7   NA   NA   NA  11  24   7
name1,name3,name4,name6,name7     4    8   12    3    4    8   7  12  10
name1,name2,name5,name6,name7    12    4    5   NA   NA   NA  12   4   5
name3,name4,name5,name6,name7    NA   NA   NA   15    3   28  15   3  28

然后我只保留名称列和最后三列

merge1 <- DF[c(1,8,9,10)]

然后我为接下来的两个data.frames执行相同的过程并将其命名为merge2。然后我将合并merge1和merge 2。

total1 <- merge(x = merge1, y = merge2, by = "Name", all = TRUE)

我将继续一次合并两个数据帧,然后将Totals data.frames合并为一起两个。我得到了我想要的最终结果,但这是一个及时的过程而且效率不高。

我认为我可以做到的另一种方式可能是对所有data.frames做一个rbind然后如果在Name列中任何行与另一行有相同的名称列表然后再创建一行,添加列A,添加B列并获得C列的平均值。但我不知道该怎么做。

以下是我想用rind

的例子
Name                              A     B     C
name1,name2,name3,name4,name5    11    24     7
name1,name3,name4,name6,name7     4     8    12
name1,name2,name5,name6,name7    12     4     5 
name3,name4,name5,name6,name7    15     3    28 
name1,name3,name4,name6,name7     3     4     8

最终结果看起来像这样

Name                              A     B     C
name1,name2,name3,name4,name5    11    24     7
name1,name3,name4,name6,name7     7    12    10
name1,name2,name5,name6,name7    12     4     5 
name3,name4,name5,name6,name7    15     3    28 

同样,我相信有更有效的方法来完成我想要的比我目前所做的更多,所以任何帮助都将不胜感激。

2 个答案:

答案 0 :(得分:3)

我认为您的第二种方法是可行的,您可以使用data.tabledplyr来实现这一目标。

使用data.table执行以下几个步骤。首先,如果您的数据框为abcdef,... 做:

DF <- do.call(rbind, list(abc,def,...))

现在您可以将它们转换为data.table

DT <- data.table(DF)

并简单地执行类似

的操作
DTres <- DT[,.(A=sum(A, na.rm=T), B=sum(B, na.rm=T), C=mean(C,na.rm=T)),by=name]

仔细检查data.table插图,以便更好地了解该工具包的工作原理。

答案 1 :(得分:1)

我们可以使用dplyr

library(dplyr)
bind_rows(abc, def, ...) %>%
   group_by(name) %>%
   summarise(A= sum(A, na.rm= TRUE),
            B = sum(B, na.rm= TRUE),
            C = mean(C, na.rm=TRUE))