【问题标题】:Use `.` syntax and `with = FALSE` in one data.table call在一次 data.table 调用中使用 `.` 语法和 `with = FALSE`
【发布时间】:2020-06-24 18:21:01
【问题描述】:

假设我想要一个 data.table 包含用户提供的列和程序员指定的重命名,例如,以下代码:

iris <- data.table::data.table(iris)
# details varies, users are smart and don't specify columns that will be renamed.
details <- c('Sepal.Length', 'Sepal.Width')
cbind(iris[, .(Type = Species)], iris[, details, with = FALSE])

我对选择和重命名列的最有效和最优雅的方法感兴趣。它是什么?我们无法比上面的cbind() 做得更好。 data.table 的大小合理,例如 500.000 行 x 8 列。

附录

我已经用微基准运行了 Akrun 提供的解决方案,它们的表现相当不错:

> microbenchmark(
  cbind1 = cbind(iris3000[, .(Type = Species)], iris3000[, details, with = FALSE]),
  cbind2 = cbind(iris3000[, .(Type = Species)], iris3000[, ..details]),
  assignment = iris3000[, ..details][, Type := iris3000$Species][],
  setnames1 = setnames(iris3000[, .SD, .SDcols = c("Species", details)],  "Species", "Type")[],
  setnames2 = setnames(iris3000[,  c("Species", ..details)], 1, "Type")[],
  times = 500L
)
Unit: milliseconds
       expr      min       lq     mean   median       uq       max neval
     cbind1 4.900362 5.304078 6.306950 5.414371 5.558222  21.77936   500
     cbind2 4.910121 5.296428 6.720642 5.411720 5.514940 221.38992   500
 assignment 2.108325 2.284778 2.738970 2.333464 2.394961  18.55119   500
  setnames1 2.155007 2.372021 2.857554 2.423696 2.483803  20.26001   500
  setnames2 1.832926 2.048634 2.960401 2.095429 2.145081 204.90523   500

details &lt;- NULL 的情况也可以,而且速度更快。

【问题讨论】:

  • with=FALSEj 中禁用类似于with() 的接口,使data.table 接口成为类似data.frame 的接口,因此您不能使用.(),请在?with 阅读更多内容

标签: r data.table


【解决方案1】:

我们可以在.SDcols 中指定要选择的列,将.SD 设置为子集,并使用setnames 更改特定的列名称

setnames(iris[, .SD, .SDcols = c("Species", details)], "Species", "Type")[]

使用with = FALSE的OP代码可以缩短为..

cbind(iris[, .(Type = Species)], iris[, ..details])

或者代替cbind,可以做一个作业

iris[, ..details][, Type := iris$Species][]

或者另一种选择是

setnames(iris[,  c("Species", ..details)], 1, "Type")[]
#          Type Sepal.Length Sepal.Width
#  1:    setosa          5.1         3.5
#  2:    setosa          4.9         3.0
#  3:    setosa          4.7         3.2
#  4:    setosa          4.6         3.1
#  5:    setosa          5.0         3.6
# ---                                   
#146: virginica          6.7         3.0
#147: virginica          6.3         2.5
#148: virginica          6.5         3.0
#149: virginica          6.2         3.4
#150: virginica          5.9         3.0

【讨论】:

  • 谢谢,这太棒了,我不知道[] 技巧。我在问题中添加了基准以展示您的解决方案。所有都改进了我们当前的代码:)
  • 在最后一个中使用1L 似乎稍微快一些,但它只是稍微
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2017-04-22
  • 2017-09-29
  • 2021-08-11
  • 1970-01-01
  • 2014-06-17
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多