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/