对于两个逻辑矢量,x
并且y
,长度> 1E8的,什么是计算2×2交叉表格最快的方法?
我怀疑答案是用C/C++编写它,但我想知道R中是否有一些关于这个问题已经非常聪明,因为它并不罕见.
示例代码,对于300M条目(如果3E8太大,可以让N = 1E8;我选择的总大小不到2.5GB(2.4GB).我的目标密度为0.02,只是为了让它更有趣(可以使用稀疏向量,如果这有帮助,但类型转换可能需要时间).
set.seed(0)
N = 3E8
p = 0.02
x = sample(c(TRUE, FALSE), N, prob = c(p, 1-p), replace = TRUE)
y = sample(c(TRUE, FALSE), N, prob = c(p, 1-p), replace = TRUE)
Run Code Online (Sandbox Code Playgroud)
一些明显的方法:
table
bigtabulate
sum(x & y)
)data.table
parallel
从multicore
包(或新parallel
包)我已经尝试了前三个选项(请参阅我的回答),但我觉得必须有更好更好的东西.
我觉得这table
很慢. bigtabulate
对于一对逻辑向量来说似乎有些过分.最后,进行vanilla逻辑运算看起来像一个kludge,它看了每个向量太多次(3X?7X?),更不用说它在处理期间填充了大量额外的内存,这是一个巨大的时间浪费.
向量乘法通常是一个坏主意,但是当向量稀疏时,可能会因为存储它而获得优势,然后使用向量乘法.
随意改变N
和p
,如果将展示的制表功能,任何有趣的行为.:)
更新1.我的第一个答案给出了三种天真方法的时间,这是相信table
速度缓慢的基础.然而,要意识到的关键是"逻辑"方法效率极低.看看它在做什么:
sum
)我有调查数据SPSS
,Stata
其~730 MB
大小.~800MB
如果我正在处理这些数据,那么这些程序中的每一个程序也会占用大约你期望的空间量().
我一直在尝试拿起R
,所以试图加载这些数据R
.无论我尝试什么方法(read.dta
从stata
文件,fread
从csv
文件,read.spss
从spss
文件),R
对象(使用测量object.size()
)2.6 to 3.1 GB
在大小之间.如果我将对象保存在一个R
文件中,那就小于100 MB
,但加载时它与之前的大小相同.
任何使用调查包分析数据的尝试,特别是如果我尝试和subset
数据,都需要比等效命令更长的时间stata
.
例如'hhpers'
,我的数据中有一个家庭大小变量'hh'
,按变量加权'hhwt'
,子集加权'htype'
R代码:
require(survey)
sv.design <- svydesign(ids = ~0,data = hh, weights = hh$hhwt)
rm(hh)
system.time(svymean(~hhpers,sv.design[which
(sv.design$variables$htype=="rural"),]))
Run Code Online (Sandbox Code Playgroud)
将R使用的内存推高到6 GB并花费很长时间 - 用户系统已经过去
3.70 1.75 144.11
stata中的等效操作
svy: mean hhpers …
Run Code Online (Sandbox Code Playgroud) 我原以为R有一个标准的开销用于存储对象(24个字节,似乎,至少对于整数向量),但一个简单的测试显示它比我意识到的更复杂.例如,采用长度为100的整数向量(使用随机抽样,希望避免任何可能存在的偷偷摸摸的序列压缩技巧),我发现不同长度的向量可以具有相同的大小,如下所示:
> N = 100
> V = vector(length = 100)
> for(L in 1:N){
+ z = sample(N, L, replace = TRUE)
+ V[L] = object.size(z)
+ }
>
> options('width'=88)
> V
[1] 48 48 56 56 72 72 72 72 88 88 88 88 104 104 104 104 168 168 168 168
[21] 168 168 168 168 168 168 168 168 168 168 168 168 176 176 184 184 192 192 200 200
[41] 208 …
Run Code Online (Sandbox Code Playgroud) R似乎每个整数需要四个字节的存储空间,即使对于小整数也是如此:
> object.size(rep(1L, 10000))
40040 bytes
Run Code Online (Sandbox Code Playgroud)
而且,更重要的是,即使是因素:
> object.size(factor(rep(1L, 10000)))
40456 bytes
Run Code Online (Sandbox Code Playgroud)
我认为,特别是在后一种情况下,这可以更好地处理.有没有一种解决方案可以帮助我将这种情况的存储要求降低到每行八位甚至两位?也许是一种在raw
内部使用该类型进行存储的解决方案,但其行为类似于正常因素.这个bit
包提供了这个位,但是我没有找到任何相似的因素.
我的数据框只有几百万行消耗千兆字节,这是一个巨大的浪费内存和运行时间(!).压缩将减少所需的磁盘空间,但同样会以运行时为代价.
有关: