以简单的方式聚合数据框,同时保持原始顺序

前端之家收集整理的这篇文章主要介绍了以简单的方式聚合数据框,同时保持原始顺序前端之家小编觉得挺不错的,现在分享给大家,也给大家做个参考。
我在聚合数据框时遇到一些麻烦,同时保持组的原始顺序(基于数据框中的第一次出现的顺序).我已经设法做到了,但希望有一个更简单的方法解决它.

以下是要处理的示例数据集:

  1. set.seed(7)
  2. sel.1 <- sample(1:5,20,replace = TRUE) # selection vector 1
  3. sel.2 <- sample(1:5,replace = TRUE)
  4. add.1 <- sample(81:100) # additional vector 1
  5. add.2 <- sample(81:100)
  6. orig.df <- data.frame(sel.1,sel.2,add.1,add.2)

需要注意的一些要点:有两个选择列可确定数据如何组合在一起.他们将是相同的,他们的名字是已知的.我在这些数据中只添加了两列,但可能还有更多.我给出了以’sel’和’add’开头的列名,以便更容易理解,但实际数据有不同的名称(因此虽然grep技巧很酷,但在这里它们没用).

我要做的是根据’sel’列将数据框聚合成组,并将所有’添加’列加在一起.这很简单,使用如下聚合:

  1. # Get the names of all the additional columns
  2. all.add <- names(orig.df)[!(names(orig.df)) %in% c("sel.1","sel.2")]
  3. aggr.df <- aggregate(orig.df[,all.add],by=list(sel.1 = orig.df$sel.1,sel.2 = orig.df$sel.2),sum)

问题是结果是由’sel’列排序的;我希望它根据每个组首次出现在原始数据中进行排序.

以下是我做这项工作的最佳尝试:

  1. ## Attempt 1
  2. # create indices for each row (x) and find the minimum index for each range
  3. index.df <- aggregate(x = 1:nrow(orig.df),min)
  4. # Make sure the x vector (indices) are in the right range for aggr.df
  5. index.order <- (1:nrow(index.df))[order(index.df$x)]
  6. aggr.df[index.order,]
  7.  
  8. ## Attempt 2
  9. # get the unique groups. These are in the right order.
  10. unique.sel <- unique(orig.df[,c("sel.1","sel.2")])
  11. # use sapply to effectively loop over data and sum additional columns.
  12. sums <- t(sapply(1:nrow(unique.sel),function (x) {
  13. sapply(all.add,function (y) {
  14. sum(aggr.df[which(aggr.df$sel.1 == unique.sel$sel.1[x] &
  15. aggr.df$sel.2 == unique.sel$sel.2[x]),y])
  16. })
  17. }))
  18. data.frame(unique.sel,sums)

虽然这些给了我正确的结果,但我希望有人可以指出一个更简单的解决方案.如果解决方案适用于标准R安装附带的软件包,那将是更好的选择.

我已经查看了聚合和匹配的文档,但我找不到答案(我想我希望像聚合的“keep.original.order”参数一样).

任何帮助将非常感激!

更新:(万一有人偶然发现)

这是我尝试再过几天后能找到的最干净的方式:

  1. unique(data.frame(sapply(names(orig.df),function(x){
  2. if(x %in% c("sel.1","sel.2")) orig.df[,x] else
  3. ave(orig.df[,x],orig.df$sel.1,orig.df$sel.2,FUN=sum)},simplify=FALSE)))
有点难以阅读,但它给你你想要的东西,我添加了一些评论来澄清.
  1. # Define the columns you want to combine into the grouping variable
  2. sel.col <- grepl("^sel",names(orig.df))
  3. # Create the grouping variable
  4. lev <- apply(orig.df[sel.col],1,paste,collapse=" ")
  5. # Split and sum up
  6. data.frame(unique(orig.df[sel.col]),t(sapply(split(orig.df[!sel.col],factor(lev,levels=unique(lev))),apply,2,sum)))

输出看起来像这样

  1. sel.1 sel.2 add.1 add.2
  2. 1 5 4 96 84
  3. 2 2 2 175 176
  4. 3 1 5 384 366
  5. 5 2 5 95 89
  6. 6 4 1 174 192
  7. 7 2 4 82 87
  8. 8 5 3 91 98
  9. 10 3 2 189 178
  10. 11 1 4 170 183
  11. 14 1 1 100 91
  12. 17 3 3 81 82
  13. 19 5 5 83 88
  14. 20 2 3 90 96

猜你在找的设计模式相关文章