因素是否比数字更有效地存储在data.table中?

pic*_*ick 19 memory r data.table

我虽然在某处读过(不记得在哪里)因为这些因素实际上并不比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
Run Code Online (Sandbox Code Playgroud)

Mat*_*wle 25

您可能正在记住data.table FAQ 2.17,其中包含:

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

(该部分已于2012年7月在v1.8.2的FAQ中添加.)

使用字符而非因素可以帮助堆叠(rbindlist)等任务.由于c()两个字符向量中的一个只是串联,而c()两个因子列中的一个需要遍历并联合两个因子级别,这两个因子级别更难编码并且执行时间更长.

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

这取决于你正在做什么,但操作已经针对characterdata.table 进行了优化,这就是我们的建议.基本上它保存了一个跳(到级别),我们可以通过比较指针值而不是跳跃来比较不同表中的两个字符列,甚至是全局缓存.

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

  • @jenesaisquoi https://cran.r-project.org/doc/manuals/r-devel/R-ints.html#The-CHARSXP-cache然后在源代码中搜索mkChar(). (3认同)