因子在 data.table 中的存储效率是不是比字符更有效?

Posted

技术标签:

【中文标题】因子在 data.table 中的存储效率是不是比字符更有效?【英文标题】:Are factors stored more efficiently in data.table than characters?因子在 data.table 中的存储效率是否比字符更有效? 【发布时间】:2016-04-24 02:29:33 【问题描述】:

虽然我在某个地方(不记得在哪里)读到过这些因素实际上并不比 data.table 中的字符向量更有效。这是真的?我在争论是否继续使用因子将各种向量存储在 data.table 中。 object.size 的近似测试似乎表明并非如此。

chars <- data.table(a = sample(letters, 1e5, TRUE))           # chars (not really)
string <- data.table(a = sample(state.name, 1e5, TRUE))       # strings
fact <- data.table(a = factor(sample(letters, 1e5, TRUE)))    # factor
int <- data.table(a = sample(1:26, 1e5, TRUE))                # int

mbs <- function(...) 
    ns <- sapply(match.call(expand.dots=TRUE)[-1L], deparse)
    vals <- mget(ns, .GlobalEnv)
    cat('Sizes:\n',
        paste('\t', ns, ':', round(sapply(vals, object.size)/1024/1024, 3), 'MB\n'))


## Get approximate sizes?
mbs(chars, string, fact, int)
# Sizes:
#    chars : 0.765 MB
#    string : 0.766 MB
#    fact : 0.384 MB
#    int : 0.382 MB

【问题讨论】:

其他阅读此问题的人可能对 R 的一般行为感兴趣;根据 Hadley Wickham 的说法,“R 有一个全局字符串池。这意味着每个唯一的字符串只存储在一个位置,因此字符向量占用的内存比您预期的要少。”见adv-r.had.co.nz/memory.html 【参考方案1】:

您可能还记得 data.table FAQ 2.17,其中包含:

stringsAsFactors 在 data.frame 中默认为 TRUE,但在 data.table 中为 FALSE,以提高效率。由于在 R 中添加了全局字符串缓存,字符项是指向单个缓存字符串的指针,转换为因子不再有性能优势。

(该部分已于 2012 年 7 月添加到 v1.8.2 的常见问题解答中。)

在堆叠(rbindlist)之类的任务中,使用字符而不是因子有很大帮助。由于两个字符向量的 c() 只是串联,而两个因子列的 c() 需要遍历和合并两个因子级别,这更难编码并且执行时间更长。

您注意到的是 64 位机器上 RAM 消耗的差异。因子存储为级别中项目的integer 向量查找。 integer 类型是 32 位的,即使在 64 位平台上也是如此。但是指针(character 向量是什么)在 64 位机器上是 64 位的。因此,在 64 位机器上,字符列将使用两倍于因子列的 RAM。 32位没有区别。但是,通常这种成本会被字符向量上可能的更简单和更快的指令所抵消。 [旁白:由于因子是integer,它们不能包含超过 20 亿个唯一字符串。 character 列没有这个限制。]

这取决于您在做什么,但操作已针对 data.table 中的 character 进行了优化,因此我们建议您这样做。基本上它节省了一个跃点(到关卡),我们可以通过比较指针值来比较不同表中的两个字符列,而根本不跳转,甚至到全局缓存。

这也取决于列的基数。假设该列有 100 万行并包含 100 万个唯一字符串。将其存储为因子将需要 100 万个字符向量用于关卡,再加上 100 万个整数向量指向关卡的元素。那是 (4+8)*1e6 字节。另一方面,字符向量不需要级别,它只是 8*1e6 字节。在这两种情况下,全局缓存都以相同的方式存储 100 万个唯一字符串,因此无论如何都会发生这种情况。在这种情况下,字符列将比它是一个因素使用更少的 RAM。仔细检查用于计算 RAM 使用量的内存工具是否正确计算。

【讨论】:

@jenesaisquoi cran.r-project.org/doc/manuals/r-devel/… 然后在源代码中搜索 mkChar()。

以上是关于因子在 data.table 中的存储效率是不是比字符更有效?的主要内容,如果未能解决你的问题,请参考以下文章

在data.table中具有指定变量的引用列

mongodb为啥比mysql快

R 3.6.0 中的 data.table 包中是不是存在内存泄漏?

plyr 啥时候比 data.table 好? [关闭]

量化交易——因子选股多因子选股策略

在 data.table 中分配多个 lapplys?