r - 为什么列选择的 data.table 表示法会影响速度
问题描述
速度似乎有所不同,具体取决于您如何指定要从 data.table 中选择的列:x[, .(var)]
vs x[, c('var')]
。原因可能很明显,但是在帮助页面.()
中,list()
符号c()
似乎可以互换使用。我使用相当大的数据集,所以这对我来说有点重要:-)
示例(调用顺序不影响速度):
x <- as.data.table(as.character(rnorm(20000000,1,0.5)))
setkey(x, V1)
tic(); x[, .(V1)]; toc()
25.08 sec elapsed
tic(); x[, c('V1')]; toc()
0.28 sec elapsed
tic(); x[, 1]; toc()
0.02 sec elapsed
> sessionInfo()
R version 3.6.1 (2019-07-05)
Platform: x86_64-w64-mingw32/x64 (64-bit)
Running under: Windows 10 x64 (build 18362)
attached base packages:
[1] stats graphics grDevices utils datasets methods base
other attached packages:
[1] tictoc_1.0 data.table_1.12.8
loaded via a namespace (and not attached):
[1] compiler_3.6.1 tools_3.6.1 lifecycle_0.2.0 rlang_0.4.6
解决方案
您发现了一个错误(在此处提交的问题)-data.table
正在尝试确定 的输出[]
是否已键入;为此,它正在运行一个内部is.sorted
函数。这在一个巨大的唯一字符串表上非常慢。
幸运的是,我们可以进行静态分析并意识到您的输出表实际上是键控的——没有子集,键列 ( V1
) 没有改变。因此排序顺序不能改变,您的输出也将按V1
.
此逻辑内置于PR 以解决此问题- 您可以使用 来测试它remotes::install_github('Rdatatable/data.table@fix_sorting_on_sorted')
,但需要注意的是这是包的最前沿版本,或者您可以等到它合并到 master 或新版本发布到 CRAN。
与此同时,这里有一个解决方法:
setkey(x, NULL)
system.time(x[ , .(V1)])
# user system elapsed
# 0.120 0.087 0.213
当然,这会阻止以后的处理识别您的数据已排序及其效率......
在这种情况下(!仅在这种情况下——小心使用!!!)——如果你自己确定数据已经排序V1
——你可以立即恢复密钥:
setattr(x, 'sorted', 'V1')
[
更一般地说,使用, [[
,$
等选择之间的细微差别[
往往是最慢的,因为我们做了很多“静态查询分析”来帮助提高代码的效率,这会带来性能成本,我们希望这会几乎每次都变小。任何时候这个成本都不小,应该是bug。还有一些工作正在积极地尝试并提供减少这种开销的快捷方式,例如参见这个 PR
推荐阅读
- nginx - nginx:提供不同反向代理应用程序的静态文件
- sql-server - 如何在 vb.net 睡眠期间在后台运行 .Gif 图像
- php - 根据值跳过导入行
- javascript - 基于for循环添加div类
- php - 测试数据库中是否存在数字,如果存在则创建新的
- powershell - 用于 PowerShell 功能的自定义 -PassThru 开关
- hyperledger-fabric - 以太坊 vs Hyperledger Fabric
- redis - Redis active - 跨数据中心/Kubernetes 集群的主动复制
- random - 如何使用 Numba xoroshiro128p 创建简单的随机数组
- c# - 如何简单地从 appsettings.json 读取