【问题标题】:how to avoid an optimization warning in data.table如何避免 data.table 中的优化警告
【发布时间】:2013-04-22 02:20:01
【问题描述】:

我有以下代码:

> dt <- data.table(a=c(rep(3,5),rep(4,5)),b=1:10,c=11:20,d=21:30,key="a")
> dt
    a  b  c  d
 1: 3  1 11 21
 2: 3  2 12 22
 3: 3  3 13 23
 4: 3  4 14 24
 5: 3  5 15 25
 6: 4  6 16 26
 7: 4  7 17 27
 8: 4  8 18 28
 9: 4  9 19 29
10: 4 10 20 30
> dt[,lapply(.SD,sum),by="a"]
Finding groups (bysameorder=TRUE) ... done in 0secs. bysameorder=TRUE and o__ is length 0
Optimized j from 'lapply(.SD, sum)' to 'list(sum(b), sum(c), sum(d))'
Starting dogroups ... done dogroups in 0 secs
   a  b  c   d
1: 3 15 65 115
2: 4 40 90 140
> dt[,c(count=.N,lapply(.SD,sum)),by="a"]
Finding groups (bysameorder=TRUE) ... done in 0secs. bysameorder=TRUE and o__ is length 0
Optimization is on but j left unchanged as 'c(count = .N, lapply(.SD, sum))'
Starting dogroups ... The result of j is a named list. It's very inefficient to create the same names over and over again for each group. When j=list(...), any names are detected, removed and put back after grouping has completed, for efficiency. Using j=transform(), for example, prevents that speedup (consider changing to :=). This message may be upgraded to warning in future.
done dogroups in 0 secs
   a count  b  c   d
1: 3     5 15 65 115
2: 4     5 40 90 140

如何避免可怕的“非常低效”警告?

我可以在加入前添加count 列:

> dt$count <- 1
> dt
    a  b  c  d count
 1: 3  1 11 21     1
 2: 3  2 12 22     1
 3: 3  3 13 23     1
 4: 3  4 14 24     1
 5: 3  5 15 25     1
 6: 4  6 16 26     1
 7: 4  7 17 27     1
 8: 4  8 18 28     1
 9: 4  9 19 29     1
10: 4 10 20 30     1
> dt[,lapply(.SD,sum),by="a"]
Finding groups (bysameorder=TRUE) ... done in 0secs. bysameorder=TRUE and o__ is length 0
Optimized j from 'lapply(.SD, sum)' to 'list(sum(b), sum(c), sum(d), sum(count))'
Starting dogroups ... done dogroups in 0 secs
   a  b  c   d count
1: 3 15 65 115     5
2: 4 40 90 140     5

但这看起来不太优雅......

【问题讨论】:

  • 您想“抑制”警告还是高效地做事?
  • 我从来没有说过“压制”。我说“避免”,意思是我想做正确的事情,让我的代码正常、高效地运行,这样就不需要警告了。
  • 显然我不太确定您是要“避免”“看到”警告还是“避免”“拥有”该警告。
  • @djhuro,这样做:options(datatable.verbose = TRUE) 然后尝试代码。
  • @Arun:感谢您的回答以及您代表我提出的问题

标签: r data.table


【解决方案1】:

我能想到的一种方法是通过引用分配count:

dt.out <- dt[, lapply(.SD,sum), by = a]
dt.out[, count := dt[, .N, by=a][, N]]
# alternatively: count := table(dt$a)

#    a  b  c   d count
# 1: 3 15 65 115     5
# 2: 4 40 90 140     5

编辑 1:我仍然认为这只是消息而不是警告。但是,如果您仍然想避免这种情况,请执行以下操作:

dt.out[, count := as.numeric(dt[, .N, by=a][, N])]

编辑 2: 非常有趣。执行相当于多个:= 分配不会产生相同的消息。

dt.out[, `:=`(count = dt[, .N, by=a][, N])]
# Detected that j uses these columns: a 
# Finding groups (bysameorder=TRUE) ... done in 0.001secs. bysameorder=TRUE and o__ is length 0
# Detected that j uses these columns: <none> 
# Optimization is on but j left unchanged as '.N'
# Starting dogroups ... done dogroups in 0 secs
# Detected that j uses these columns: N 
# Assigning to all 2 rows
# Direct plonk of unnamed RHS, no copy.

【讨论】:

  • 这会生成警告“第 1 项的 RHS 已重复。命名向量或循环列表 RHS。”
  • 你怎么说这是一个警告?它没有说任何关于效率低下的事情......这只是一个信息。无论如何,我已经进行了编辑,没有收到该消息。
  • 我认为您可能会发现dt[, .N, by=a][['N']] 更有效,因为它在简单的子集化时不需要调用[.data.table 的开销。
【解决方案2】:

此解决方案会删除有关命名元素的消息。但是你必须在之后把名字放回去。

require(data.table)
options(datatable.verbose = TRUE)

dt <- data.table(a=c(rep(3,5),rep(4,5)),b=1:10,c=11:20,d=21:30,key="a")

dt[, c(.N, unname(lapply(.SD, sum))), by = "a"]

输出

> dt[, c(.N, unname(lapply(.SD, sum))), by = "a"]
Finding groups (bysameorder=TRUE) ... done in 0secs. bysameorder=TRUE and o__ is length 0
Optimization is on but j left unchanged as 'c(.N, unname(lapply(.SD, sum)))'
Starting dogroups ... done dogroups in 0.001 secs
   a V1 V2 V3  V4
1: 3  5 15 65 115
2: 4  5 40 90 140

【讨论】:

  • 不错(更好)的替代品。在末尾添加.N 可以更轻松地在以后使用setnames(dt.out, c(names(dt), "N")) 设置名称(更容易一些)。
  • 这明显慢:Starting dogroups ... done dogroups in 0.277 secs vs Starting dogroups ... done dogroups in 2.929 secs
  • 我将你的(慢)与我的或 @arun 的(都快)进行比较
  • @djhurio,尝试使用大的data.table(1e7 x 4 列或更多列),我观察到与 sds 相同的效果。
猜你喜欢
  • 1970-01-01
  • 2016-12-25
  • 2021-02-04
  • 2021-04-29
  • 1970-01-01
  • 2019-02-21
  • 1970-01-01
  • 2014-03-21
  • 1970-01-01
相关资源
最近更新 更多