r - 为小整数或级别少的因子节省存储空间

标签 r performance memory

R 似乎每个整数都需要四个字节的存储空间,即使对于小整数也是如此:

> object.size(rep(1L, 10000))
40040 bytes

而且,更重要的是,即使对于因素:

> object.size(factor(rep(1L, 10000)))
40456 bytes

我认为,尤其是在后一种情况下,这可以处理得更好。有没有一种解决方案可以帮助我将这种情况的存储要求减少到每行八位甚至两位?也许是一个在内部使用 raw 类型进行存储的解决方案,但在其他方面表现得像正常因子。 bit 包提供了这一点,但我还没有发现任何类似的因素。

我的数据帧只有几百万行,却消耗了千兆字节,这是内存和运行时间的巨大浪费(!)。压缩将减少所需的磁盘空间,但同样会牺牲运行时间。

相关:

最佳答案

既然您提到了raw(并假设您的因子级别少于256个) - 如果内存是您的瓶颈并且CPU时间不是,您可以执行先决条件转换操作t。例如:

f = factor(rep(1L, 1e5))
object.size(f)
# 400456 bytes

f.raw = as.raw(f)
object.size(f.raw)
#100040 bytes

# to go back:
identical(as.factor(as.integer(f.raw)), f)
#[1] TRUE

如果您有兴趣的话,您还可以单独保存因子水平并恢复它们,但就分组和所有操作而言,您可以使用 raw 来完成所有操作,而永远不会回到因素(演示除外)。

如果您在使用此方法时遇到问题的特定用例,请发布它,否则我认为这应该可以正常工作。

<小时/>

这是 byte.factor 类的起点:

byte.factor = function(f) {
  res = as.raw(f)
  attr(res, "levels") <- levels(f)
  attr(res, "class") <- "byte.factor"
  res
}

as.factor.byte.factor = function(b) {
  factor(attributes(b)$levels[as.integer(b)], attributes(b)$levels)
}

所以你可以做这样的事情:

f = factor(c('a','b'), letters)
f
#[1] a b
#Levels: a b c d e f g h i j k l m n o p q r s t u v w x y z

b = byte.factor(f)
b
#[1] 01 02
#attr(,"levels")
# [1] "a" "b" "c" "d" "e" "f" "g" "h" "i" "j" "k" "l" "m" "n" "o" "p" "q" "r" "s"
#[20] "t" "u" "v" "w" "x" "y" "z"
#attr(,"class")
#[1] "byte.factor"

as.factor.byte.factor(b)
#[1] a b
#Levels: a b c d e f g h i j k l m n o p q r s t u v w x y z

如果您想让 as.factor 通用并只添加任何函数,请查看 data.table 如何覆盖 rbind.data.frame你想添加。一切都应该非常简单。

关于r - 为小整数或级别少的因子节省存储空间,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/17718326/

相关文章:

r - 绕过R中循环内的错误

C/C++ : is GOTO faster than WHILE and FOR?

c++ - for循环的初始化超出其范围

python - 执行内存保存列聚合的Pythonic方法是什么?

python - R 和 Python 的不同多项式回归系数

r - 使用填充美学两次,具有两种不同的比例

R 代表函数返回错误数量的元素

python - SQLAlchemy "default"与 "server_default"性能对比

mysql - 将 ElastiCache 与 RDS 结合使用以提高读/写性能

python - 使用 Theano 在 CPU 上训练简单的 MLP 时,内存逐渐增加直至崩溃