r - 快速数据表过滤
问题描述
我有一个用例,我想快速重复过滤数据表。我有一种感觉,如果我使用像df[val>0,]
scan is 这样的简单过滤器O(N)
,但如果我只是将val
字段设置为键,那么我应该能够更快地过滤,但不确定如何过滤。作为一个例子,我做了以下
排序的数据表
df_sort = data.table(id = seq(1, 100000), val = runif(100000, 0, 1))
setkeyv(df_sort, c('val')
常规数据表
df = data.table(id = seq(1, 100000), val = runif(100000, 0, 1))
我想做的情况是找到 uniqueid
的 for val > tol
。使用rbenchmark
我做了以下
benchmark('raw' = { l = length(unique(df$id[df$val >=0.1]))}, 'sort' = {l = length(unique(df_sort$id[df_sort$val >=0.1]))}, replications=20)
我得到的结果显示两者之间没有区别。
test replications elapsed relative user.self sys.self user.child sys.child
1 raw 20 0.440 1.005 0.494 0 0 0
2 sort 20 0.438 1.000 0.540 0 0 0
有人可以就如何做到这一点给出一些指示吗?甚至可能吗?
编辑
在评论中尝试了一个建议,结果更糟。不知道为什么。
benchmark('raw' = { l = df[val >=0.1, uniqueN(id)]}, 'sort' = {l = df_sort[val >=0.1, uniqueN(id)]}, replications=200)
test replications elapsed relative user.self sys.self user.child sys.child
1 raw 200 0.770 1.000 0.928 0 0 0
2 sort 200 1.361 1.768 1.691 0 0 0
解决方案
好的,这里有一些适当的基准。您的两个基准中的时间单位可能不一样。
library(rbenchmark)
library(data.table)
set.seed(42)
#using sample to rule out ALTREP influence
df <- data.table(id = sample(1e7, replace = TRUE), val = runif(1e7, 0, 1))
df_sort <- copy(df)
setkey(df_sort, val)
benchmark('raw' = { l = length(unique(df$id[df$val >=0.1]))},
'sort' = {l = length(unique(df_sort$id[df_sort$val >=0.1]))},
'raw_DT' = {df[val >=0.1, uniqueN(id)]},
'sort_DT' = {df_sort[val >=0.1, uniqueN(id)]},
'raw_DT_length' = {df[val >=0.1, length(unique(id))]},
replications=20, order = "relative")
# test replications elapsed relative user.self sys.self user.child sys.child
#3 raw_DT 20 9.422 1.000 8.742 0.680 0 0
#4 sort_DT 20 9.617 1.021 8.901 0.697 0 0
#2 sort 20 15.237 1.617 14.016 1.222 0 0
#1 raw 20 15.313 1.625 14.128 1.190 0 0
#5 raw_DT_length 20 16.719 1.774 15.473 1.233 0 0
benchmark(unique_length = length(unique(df$id)),
uniqueN = uniqueN(df$id),
replications=20, order = "relative")
# test replications elapsed relative user.self sys.self user.child sys.child
#2 uniqueN 20 7.708 1.000 7.340 0.368 0 0
#1 unique_length 20 15.683 2.035 14.765 0.920 0 0
benchmark(subset_base = df$id[df$val >=0.1],
subset_data.table = df[val >=0.1, id],
subset_data.table_keyed = df_sort[val >=0.1, id],
replications=20, order = "relative")
# test replications elapsed relative user.self sys.self user.child sys.child
#1 subset_base 20 1.546 1.000 1.206 0.340 0 0
#3 subset_data.table_keyed 20 2.360 1.527 2.046 0.314 0 0
#2 subset_data.table 20 2.493 1.613 2.184 0.309 0 0
一些评论:您的基本 R 方法根本不使用 data.table 功能。Base R 逻辑运算符不使用排序;它们是简单的矢量扫描。uniqueN
应有的节拍length(unique())
。data.table
子集尚未针对>=
(尚未)进行优化。如果你真的想改进时间,你应该uniqueNSubset
用 Rcpp 编写一个函数,利用正在排序的数据(我也会对 ID 进行排序)。
> sessionInfo()
R version 3.5.0 (2018-04-23)
Platform: x86_64-apple-darwin15.6.0 (64-bit)
Running under: macOS High Sierra 10.13.4
Matrix products: default
BLAS: /System/Library/Frameworks/Accelerate.framework/Versions/A/Frameworks/vecLib.framework/Versions/A/libBLAS.dylib
LAPACK: /Library/Frameworks/R.framework/Versions/3.5/Resources/lib/libRlapack.dylib
locale:
[1] de_DE.UTF-8/de_DE.UTF-8/de_DE.UTF-8/C/de_DE.UTF-8/de_DE.UTF-8
attached base packages:
[1] stats graphics grDevices utils datasets methods base
other attached packages:
[1] data.table_1.11.2 rbenchmark_1.0.0
loaded via a namespace (and not attached):
[1] compiler_3.5.0 tools_3.5.0
推荐阅读
- google-chrome-extension - 每次重新启动 Chrome 时,解压缩的扩展程序都会自动卸载,我怎样才能始终安装它?
- java - 匿名内部类排序
- javascript - 数组的索引?
- asp.net-mvc - 我无法在 IIS 的虚拟目录中显示/浏览我的图像
- python - Python,tensorflow没有属性graphdef和cudart64_101.dll没有找到
- javascript - 如何将一个固定长宽比的 div 和一个固定宽度的 div 放在一起?
- java - 在 tomcat 中设置 max-threads = 0 不应接受用户的任何进一步请求,但它正在接受。为什么?
- delphi - Delphi7如何安装Tntcontrols
- python - 如果找到湮灭对,Django ORM 排除结果
- angular - 如何将本地存储值存储在
在角度 6?