假设我有一个名为'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)
答案 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)
被排除在基准之外,您应该会发现删除列的时间对于m1
和m2
两种方法几乎都是不可测量的(即0.00s)。这个答案是正确的,m1
和m2
之间没有区别,但是一旦时间copy(dt)
被隔离,图表应该显示0.00s的扁平线。
答案 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
一样,点击DT
与print(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}},以便进行内存效率打印!