有没有一种简单的方法来实现类似于`x [,c:= mean(a),by = b] $ c`的东西?

时间:2013-09-30 14:38:11

标签: r ggplot2 data.table

> x <- data.table(a=1:10, b=rep(1:2, 5))
> x
     a b
 1:  1 1
 2:  2 2
 3:  3 1
 4:  4 2
 5:  5 1
 6:  6 2
 7:  7 1
 8:  8 2
 9:  9 1
10: 10 2
> x[,c:=mean(a), by=b]
> y <- x$c
> y
 [1] 5 6 5 6 5 6 5 6 5 6

最终,我感谢y作为向量,我不想将c添加到data.table。是否有更简单的方法从原y获得x

当我尝试在直方图中对不同的组应用不同的权重时,会出现问题。

# here weight would be the same for all colour, but I wish they differ.
geom_freqpoly(aes(colour=group, weight=mean(y)), binwidth=1)

4 个答案:

答案 0 :(得分:4)

> with(x, ave(a, b, FUN=mean) )
 [1] 5 6 5 6 5 6 5 6 5 6

只是让data.table专家知道,我知道这可能无法很好地扩展到数百万的记录数据集,我很感谢关于这个主题的其他帖子。我一直在使用data.table来对我的大型分析产生良好的影响。这只是因为我表达了对我发布的数据参数的简单和不修改的渴望。

答案 1 :(得分:3)

您可以菊花链式连接"["运算符:

x[, c := mean(a), by=b][, c]
# [1] 5 6 5 6 5 6 5 6 5 6

"[.data.table"的结果本身就是一个data.table,所以你可以在它之后添加另一个。


我刚注意到关于不想修改x的评论。请注意,您需要以某种方式回收向量c。 R通常会为您处理此问题。如果您想手动完成,请使用:

 x[, list(c=mean(a)), by=b][, rep(c, length(x$a)/length(c))]
 # [1] 5 6 5 6 5 6 5 6 5 6

至于不修改x的动机,请注意在分配列然后随x[, c := NULL]删除它时几乎可忽略不计的开销,因此可能暂时修改DT是可行的方法。


根据@Frank的要求,这是一个简单的基准: 使用100个元素,by更快。但速度很快就会降低

# The call used for benchmarking is as follows: 
library(microbenchmark)
microbenchmark(B = as.vector(by(x$a,x$b,mean)[as.character(x$b)]), 
               D = x[, list(c=mean(a)), by=b][, rep(c, length(x$a)/length(c))]
               )



# medium sized x
N <- 1e4
x <- {set.seed(1); data.table(a=1:(N), b=sample(5, N, TRUE), key="b")}

Unit: milliseconds
 expr      min       lq   median       uq       max neval
    B 6.150740 6.284466 6.403332 7.790877 10.339314   100
    D 1.268631 1.337959 1.441184 1.525279  2.963625   100

答案 2 :(得分:2)

这是另一种不修改原始data.table的方式,但是这是一个完全人为的和不必要的约束,即你已经有了最好的解决方案。

x[, list(.I, mean(a)), by = b][order(.I), V2]
#[1] 5 6 5 6 5 6 5 6 5 6

# or for faster ordering
setkey(x[, list(.I, mean(a)), by = b], .I)$V2

答案 3 :(得分:1)

对于此特定示例,by(x$a,x$b,mean)[as.character(x$b)]应该有效。我不太了解直方图问题,所以我不知道这是否会概括你想要的方式。