使用以下方法处理复杂公式:=(data.table通过引用分配)

时间:2015-02-04 21:09:39

标签: r data.table

要计算x超过label的某些聚合,并将其添加到我可以使用以下代码的数据,mean它是:

library(data.table)  
setDT(data)[, y := mean(x), label]

但是如何计算仅在label给出的组大小超过5且否则输入0时表示。我首先尝试使用lengthnrow代替mean关键字来计算群组的大小,但这不是正确的方法,也不起作用。我使用的样本数据集:

set.seed(123)

data<-data.frame(label=sample(c("A","B"),10,replace=TRUE),x=rnorm(10))
data
#   label          x
#1      A  1.7150650
#2      B  0.4609162
#3      A -1.2650612
#4      B -0.6868529
#5      B -0.4456620
#6      A  1.2240818
#7      B  0.3598138
#8      B  0.4007715
#9      B  0.1106827
#10     A -0.5558411

我看到尝试的代码如下:

setDT(data)[, y := ifelse(nrow(x)>10,mean(x),0), label] # don't run

是错误的方向。

3 个答案:

答案 0 :(得分:5)

你可以尝试

  setDT(data)[, y:=if(.N>4) mean(x) else 0, label][]

基准

在“1e7”数据集上使用as.data.tablesetDT尝试使用两个“标签”组。所有方法都显示出相似的效率(尽管当组数增加时这可能会改变)

set.seed(198)
data <- data.frame(label=sample(LETTERS[1:2], 1e7, replace=TRUE), x=rnorm(1e7))
data1 <- copy(data)
data2 <- copy(data)
data3 <- copy(data)
n <- 5e6
David1 <- function() {setDT(data)[, y := mean(x)[.N > n] , label]}
David2 <- function() {setDT(data1)[, y := 0][, y := mean(x)[.N > n], label]}
akrun <- function() {setDT(data2)[, y:=if(.N>n) mean(x) else 0, label]}
MrFlick <- function() {setDT(data3)[, y := ifelse(length(x)>n,
                           mean(x),0), label]}

library(microbenchmark)
microbenchmark(David1(), David2(), akrun(), MrFlick(),
                      unit='relative', times=20L)
#Unit: relative
#     expr       min       lq      mean   median        uq       max neval cld
# David1() 0.9226054 1.005485 0.9975527 1.006531 0.9897817 0.9738954    20  ab
# David2() 1.0722181 1.058603 1.0388910 1.060785 1.0449793 0.9334972    20   b
#  akrun() 0.9843013 1.000373 0.9899616 1.001635 0.9917036 0.9492853    20  a 
#MrFlick() 1.0000000 1.000000 1.0000000 1.000000 1.0000000 1.0000000    20  ab

setDT更改为as.data.table

 microbenchmark(David1(), David2(), akrun(), MrFlick(), 
              unit='relative', times=20L)
 #Unit: relative
 #     expr       min        lq      mean   median       uq      max neval cld
 # David1() 0.9963619 1.0014244 0.9973844 1.006967 1.010804 1.015443    20  a 
 # David2() 1.1682075 1.1817214 1.1982023 1.185832 1.280648 1.176238    20   b
 #  akrun() 0.9885094 0.9986409 1.0085403 1.002375 1.004836 1.007429    20  a 
 #MrFlick() 1.0000000 1.0000000 1.0000000 1.000000 1.000000 1.000000    20  a 

答案 1 :(得分:5)

我建议你一起避免ifesle因为效率,因为当你不想计算平均值时放0是错误的,如果其中一个组会发生什么也会有零均值,你会如何区分它们?我只是做

setDT(data)[, y := mean(x)[.N > 4] , label][]
#     label          x          y
#  1:     A  1.7150650         NA
#  2:     B  0.4609162 0.03327823
#  3:     A -1.2650612         NA
#  4:     B -0.6868529 0.03327823
#  5:     B -0.4456620 0.03327823
#  6:     A  1.2240818         NA
#  7:     B  0.3598138 0.03327823
#  8:     B  0.4007715 0.03327823
#  9:     B  0.1106827 0.03327823
# 10:     A -0.5558411         NA

答案 2 :(得分:2)

在此示例中,x是一个向量,因此nrow()是用于查看有多少元素的错误函数。使用length

set.seed(123)
data<-data.frame(label=sample(c("A","B"),10,replace=TRUE),x=rnorm(10))
setDT(data)[, y := ifelse(length(x)>4,mean(x),0), label]
data
#     label          x          y
#  1:     A  1.7150650 0.00000000
#  2:     B  0.4609162 0.03327823
#  3:     A -1.2650612 0.00000000
#  4:     B -0.6868529 0.03327823
#  5:     B -0.4456620 0.03327823
#  6:     A  1.2240818 0.00000000
#  7:     B  0.3598138 0.03327823
#  8:     B  0.4007715 0.03327823
#  9:     B  0.1106827 0.03327823
# 10:     A -0.5558411 0.00000000