data.table列删除速度

时间:2014-01-15 17:09:08

标签: r data.table

假设我有一个名为'data'的大表。我想删除变量cI中引用的列。

这很快:

data = data[, eval(cI) := NULL]

这很慢:

data[, eval(cI) := NULL]

两种工作方式(第二种用法不打印(或返回)完整的表格。为了使第二种方法变慢,引擎盖是怎么回事?显然,涉及表格副本,但为什么?

神秘感加深了。我试着测量系统时间,第二种方法有很大不同,取决于我的时间:

> system.time(data <- data[, eval(dropI) := NULL])
   user  system elapsed
  0.004   0.000   0.003
> system.time(data[, eval(dropI) := NULL])
   user  system elapsed
  0.004   0.000   0.003
> date(); data[, eval(dropI) := NULL]; date()
[1] "Wed Jan 15 12:31:51 2014"
[1] "Wed Jan 15 12:31:58 2014"
> date(); data <- data[, eval(dropI) := NULL]; date()
[1] "Wed Jan 15 12:32:26 2014"
[1] "Wed Jan 15 12:32:26 2014"`

哦,我启用了JIT编译器(设置为3)

2 个答案:

答案 0 :(得分:3)

没有证据表明运行时存在差异:

set.seed(41)
dt <- data.table( a = rnorm(1000000), b = rnorm(1000000), c = rnorm(1000000) )

library( microbenchmark )
library( ggplot2 )

mb <- microbenchmark(  
  m1 = { x <- copy( dt ); x[ , c:= NULL ] },
  m2 = { x <- copy( dt ); x = x[ , c:= NULL ] },
  times = 500
)

# plot
qplot( data = mb, x = expr, y = time, geom = "boxplot", ylab="time [ns]", xlab = "approach" )

# show evidence
t.test( time ~ expr, data = mb )

给出

    Welch Two Sample t-test

data:  time by expr
t = -0.3622, df = 972.022, p-value = 0.7173
alternative hypothesis: true difference in means is not equal to 0
95 percent confidence interval:
 -1437943.7   989846.5
sample estimates:
mean in group m1 mean in group m2 
        10068827         10292876 

[来自Matt的编辑]这些时间包括copy(dt)似乎已完成的时间,以便可以重复删除该列。了解上面copy(dt)m1定义中m2的显示方式。这就是为什么时间变化如此可怕,以及为什么即使最好的时间也很慢。简而言之,这个基准似乎是有缺陷的。如果copy(dt)被排除在基准之外,您应该会发现删除列的时间对于m1m2两种方法几乎都是不可测量的(即0.00s)。这个答案是正确的,m1m2之间没有区别,但是一旦时间copy(dt)被隔离,图表应该显示0.00s的扁平线。

enter image description here

答案 1 :(得分:3)

为了清楚起来,@ eddi和@joran在评论中走在正确的轨道上。

绝对没有速度差异:

data = data[, eval(cI) := NULL]

data[, eval(cI) := NULL]

因为,两者都是立即执行,一致执行(0.000秒)。另一个答案就是时间copy(dt),请看我的编辑。

顺便说一下,你不需要eval,只需要括号就可以了:

data = data[, (cI) := NULL]

data[, (cI) := NULL]

发生的事情是你在控制台上输入这些命令。由于第一个是赋值,因此隐式返回值data,而R不会打印它。 R会打印第二种方法的结果。

data.frame一样,点击DTprint(DT)的速度存在巨大差异:

> DT          # very slow. R copies the whole of DT for some reason
> print(DT)   # very fast. R doesn't copy DT.

在你提出的问题中,正在拍摄副本并且你是对的。但是通过打印而不是删除列。

也许是因为DF打印了整个DF,但这还是很慢,没有人注意到R在开始将整个DF转换为DF之前也复制了DT字符形式。由于print(DT)默认打印表格的顶部和底部,这非常快,您会注意到R复制它所需的时间。无论如何,这样的事情。

我不知道为什么会这样,但它已经有一段时间了。 R的当前开发版本中有一些复制减少更改,我希望这些将减少所谓的自动打印中的副本。

在此期间,请明确调用{{1}},以便进行内存效率打印!