我有两个massive
数据集,我创建了一个简单的例子(如下)来复制我的数据结构:DT_ade
包含变量a
、d
、e
,而DT_abce
包含变量a
、b
、c
、e
。我想用a-b-c
计算d
的平均值。在下面的代码中,我根据a-e
的值合并了两个DT
,因为我对变量e
不感兴趣,所以我只选择了连接后的其余变量(a
、b
、c
、然后我计算了d
乘以a-b-c
的平均值。
library(data.table)
DT_ade = data.table(a = c("a1", "a1", "a2", "a3", "a3"),
d = c(10, 20, 30, 40, 80) ,
e = c("e1", "e2", "e2", "e2", "e3"))
DT_abce = data.table(a = c("a1", "a1", "a1", "a1", "a2", "a3", "a3"),
b = c("b1", "b1", "b2", "b2", "b2", "b2", "b2"),
c = c("c1", "c1", "c2", "c2", "c2", "c2", "c2"),
e = c("e1", "e2", "e1", "e2", "e2", "e2", "e3"))
DT_ade[
DT_abce, on=.(a, e), .(a, b, c, d)
][, .(mean_d = mean(d, na.rm=TRUE)),
.(a, b, c)]
代码在以下简单示例中工作:它给出以下输出:
a b c mean_d
1: a1 b1 c1 15
2: a1 b2 c2 15
3: a2 b2 c2 30
4: a3 b2 c2 60
但是,当将此代码应用于我的真实的数据时,由于数据的大小,我得到了以下错误消息:
Error in gforce(thisEnv, jsub, o__, f__, len__, irows) :
Internal error: Failed to allocate counts or TMP when assigning g in gforce
我想知道是否有更简单的方法来完成这个任务,例如,我可以用a-b-c
来计算d
的均值,而不生成完整的a-b-c-d
列表吗?
1条答案
按热度按时间aiqt4smr1#
我将通过一个示例来扩展Waldi对
arrow
的推荐。arrow
的好处是在处理大量数据时,以及它对数据的惰性检索/处理。虽然我在这里使用arrow::arrow_table
,这是因为它对这个示例很方便;在您的情况下,它们应该是文件系统上的parquet文件(最好是本地的)。也就是说,理想情况下,您可以将这些对象创建为:
但现在,我将用途:
其中每个对象都表示箭头对象,如下所示:没有提取数据,只是看起来像这样:
从这里开始,可以使用一个相对简单的
dplyr
管道,它还不拉取数据或执行计算:我们只需要将
%>% collect()
加到它上面,数据就实体化了(即,计算后拉入R):不要将 “
data.table
-vs-dplyr
的速度“ 与此处发生的情况混淆:你没有损失速度,因为计算是在箭头上完成的,而不是在data.table
或dplyr
中。直到collect()
,计算才真正完成(在箭头上),然后R才第一次看到数据。如果你选择as.data.table
这个数据(对于你的处理的其余部分),这是很好的。这种方法的“痛苦”在于首先要将数据放入Parquet文件中,因为数据相当大,所以当它加载到R中时,你似乎处于一种脆弱的境地:如果您的Windows计算机决定必须立即更新并重新启动,或者如果您断电(UPS/电池故障),或发生其他事情,* 您沉没 *,需要再次创建或加载所有数据。
根据我的经验,根据您的真实的数据,您可能希望先将CSV加载到R中,然后进行一些简单的处理(即转换为
POSIXt
,设置factor
s和级别等,但不整形/聚合),然后保存到parquet。保存时,底层的数据类和属性被保留。实际上,由于您正在保存一个data.table
,你可以很快地运行ds_ade %>% head() %>% collect()
并看到(1)它几乎是瞬时的,并且(2)它是一个data.table
。(POSIXt
,factor
),则它们将保留那些类。filter
ing是高效的,特别是当变量是数值的时候(但是我不是arrow
-维护者/设计者/工程师,所以我总是可能误解了,因此在这里错误地描述了懒惰的一部分)。