组合行 - 在R中汇总某些列而不是其他列

时间:2015-03-18 18:49:25

标签: r split-apply-combine

我的数据集在第1列中重复了名称,然后是其他3个数字列。

我想将重复名称的行组合成一列,并将两列相加,而另一列则另外。有一个简单的方法吗?我一直在尝试用sapply和lapply来解决这个问题并且已经阅读了很多Q& As这里似乎无法找到解决方案

Name <- c("Jeff", "Hank", "Tom", "Jeff", "Hank", "Jeff",
                       "Jeff", "Bill", "Mark")
data.Point.1 <- c(3,4,3,3,4,3,3,6,2)
data.Point.2 <- c(6,9,2,5,7,4,8,2,9)
data.Point.3 <- c(2,2,8,6,4,3,3,3,1)
data <- data.frame(Name, data.Point.1, data.Point.2, data.Point.3)

数据如下所示:

  Name data.Point.1 data.Point.2 data.Point.3
1 Jeff            3            6            2
2 Hank            4            9            2
3  Tom            3            2            8
4 Jeff            3            5            6
5 Hank            4            7            4
6 Jeff            3            4            3
7 Jeff            3            8            3
8 Bill            6            2            3
9 Mark            2            9            1

我想让它看起来像这样(总结第3列和第4列并单独留下第1列。我希望它看起来像这样:

  Name data.Point.1 data.Point.2 data.Point.3
1 Jeff            3           23           14
2 Hank            4           16            6
3  Tom            3            2            8
8 Bill            6            2            3
9 Mark            2            9            1

任何帮助都会很棒。谢谢!

3 个答案:

答案 0 :(得分:1)

另一个更直接的解决方案是使用库dplyr

library(dplyr)
data <- data %>% group_by(Name, data.Point.1) %>%  # group the columns you want to "leave alone"
  summarize(data.Point.2=sum(data.Point.2), data.Point.3=sum(data.Point.3)) # sum columns 3 and 4

如果你想要除了你想要的那些之外的所有其他列的总和&#34;单独留下&#34;然后将summarize(data.Point.2=sum(data.Point.2), data.Point.3=sum(data.Point.3))替换为summarise_each(funs(sum))

答案 1 :(得分:1)

我是这样使用data.table

setDT(data)[, c(data.Point.1 = data.Point.1[1L], 
                lapply(.SD, sum)), by=Name, 
                .SDcols = -"data.Point.1"]
#    Name data.Point.1 data.Point.2 data.Point.3
# 1: Jeff            3           23           14
# 2: Hank            3           16            6
# 3:  Tom            3            2            8
# 4: Bill            3            2            3
# 5: Mark            3            9            1

我们按Name进行分组,对于每个组,获取data.Point.1的第一个元素,对于其余列,我们使用基函数{{1}计算sum并将其循环遍历lapply列,代表数据子集.SD中的列由.SD提供,我们将.SDcols删除,以便将所有其他列提供给data.Point.1

查看HTML vignettes以获取详细信息。

答案 2 :(得分:0)

你可以尝试

library(data.table)
setDT(data)[, list(data.Point.1=data.Point.1[1L],
    data.Point.2=sum(data.Point.2), data.Point.3=sum(data.Point.3)), by=Name]
#    Name data.Point.1 data.Point.2 data.Point.3
#1: Jeff            3           23           14
#2: Hank            4           16            6
#3:  Tom            3            2            8
#4: Bill            6            2            3
#5: Mark            2            9            1

或使用base R

data$Name <- factor(data$Name, levels=unique(data$Name))
res <- do.call(rbind,lapply(split(data, data$Name), function(x) {
                x[3:4] <- colSums(x[3:4])
                x[1,]} ))

或者使用dplyr,您可以使用summarise_each来应用需要应用于多个列的功能,并cbind输出带有&#39;汇总&#39;单列的输出

library(dplyr)
res1 <- data %>%
            group_by(Name) %>% 
            summarise(data.Point.1=data.Point.1[1L])

res2 <- data %>%
            group_by(Name) %>% 
                          summarise_each(funs(sum), 3:4)
cbind(res1, res2[-1])
#   Name data.Point.1 data.Point.2 data.Point.3
#1 Jeff            3           23           14
#2 Hank            4           16            6
#3  Tom            3            2            8
#4 Bill            6            2            3
#5 Mark            2            9            1

修改

创建的数据和最初显示的数据在原始帖子中有所不同。在OP的帖子上编辑后(通过@dimitris_ps),您可以通过group_by(Name)代码中的group_by(Name, data.Point.1)替换res2 <- ..来获得预期结果。