我在聚合数据框时遇到了一些麻烦,同时保持组的原始顺序(基于数据框中首次出现的顺序)。我已经设法做到了,但希望有一种更简单的方法来解决它。
这是要处理的示例数据集:
set.seed(7)
sel.1 <- sample(1:5, 20, replace = TRUE) # selection vector 1
sel.2 <- sample(1:5, 20, replace = TRUE)
add.1 <- sample(81:100) # additional vector 1
add.2 <- sample(81:100)
orig.df <- data.frame(sel.1, sel.2, add.1, add.2)
需要注意的几点:有两个选择列来确定数据如何组合在一起。他们将是相同的,并且他们的名字是已知的。我只在此数据中添加了两列,但可能还有更多。我给出了以 'sel' 和 'add' 开头的列名,以便更容易理解,但实际数据有不同的名称(所以虽然grep
技巧很酷,但在这里它们不会有用)。
我要做的是根据“sel”列将数据框聚合成组,并将所有“添加”列加在一起。这很简单,使用aggregate
如下:
# Get the names of all the additional columns
all.add <- names(orig.df)[!(names(orig.df)) %in% c("sel.1", "sel.2")]
aggr.df <- aggregate(orig.df[,all.add],
by=list(sel.1 = orig.df$sel.1, sel.2 = orig.df$sel.2), sum)
问题是结果是按“sel”列排序的;我希望根据每个组在原始数据中的首次出现对其进行排序。
这是我完成这项工作的最佳尝试:
## Attempt 1
# create indices for each row (x) and find the minimum index for each range
index.df <- aggregate(x = 1:nrow(orig.df),
by=list(sel.1 = orig.df$sel.1, sel.2 = orig.df$sel.2), min)
# Make sure the x vector (indices) are in the right range for aggr.df
index.order <- (1:nrow(index.df))[order(index.df$x)]
aggr.df[index.order,]
## Attempt 2
# get the unique groups. These are in the right order.
unique.sel <- unique(orig.df[,c("sel.1", "sel.2")])
# use sapply to effectively loop over data and sum additional columns.
sums <- t(sapply(1:nrow(unique.sel), function (x) {
sapply(all.add, function (y) {
sum(aggr.df[which(aggr.df$sel.1 == unique.sel$sel.1[x] &
aggr.df$sel.2 == unique.sel$sel.2[x]), y])
})
}))
data.frame(unique.sel, sums)
虽然这些给了我正确的结果,但我希望有人能指出一个更简单的解决方案。如果该解决方案适用于标准 R 安装附带的软件包,那将是更可取的。
我查看了aggregate
and的文档match
,但找不到答案(我想我希望有类似的“keep.original.order”参数aggregate
)。
任何帮助将非常感激!
更新:(以防有人偶然发现)
这是我尝试了几天后能找到的最干净的方法:
unique(data.frame(sapply(names(orig.df), function(x){
if(x %in% c("sel.1", "sel.2")) orig.df[,x] else
ave(orig.df[,x], orig.df$sel.1, orig.df$sel.2, FUN=sum)},
simplify=FALSE)))