因子与字符的效率 - 对象大小

Efficiency of factor vs. characters - object size

我遇到了一些奇怪的事情。我一直认为如果可能的话将数据存储为因子变量,如果有意义的话会导致更好的存储效率。

但是当我看到这个时:

object.size(c( "A", "B", "B", "0", "A", "AB", "0")) # 720 Bytes
gr <- factor(c( "A", "B", "B", "0", "A", "AB", "0"))
object.size(gr) # 336 Bytes

那么因子变量比字符需要更多的存储空间。那么我读到的关于存储效率的内容是不是全错了?

是否有一个例子可以让初学者看到因子使用的优势?

此致, 纳丁

粗略地说,一个因子是一个整数向量,带有一个列出类别名称的 levels 属性(一个字符向量)和一个告诉 R 它是一个因子的 class 属性(另一个字符向量) .

与相同长度的字符向量相比,较短的因子往往需要 更多 内存,因为存储因子属性的成本超过了存储整数所节省的成本字符串。这是一个极端的例子来说明这一点:

x <- c("a", "b")
f <- factor(x)

class(f)
# [1] "factor"

unclass(f)
# [1] 1 2
# attr(,"levels")
# [1] "a" "b"

存储 f 需要同时存储整数向量 c(1L, 2L) 字符向量 c("a", "b")。在这种情况下,整数向量是完全多余的,因为 c("a", "b") 首先编码了我们需要的所有信息。

object.size(f)
# 568 bytes
object.size(x)
# 176 bytes

当水平有大量重复时,存储因子变得更有效。

g <- gl(2L, 1e06L, labels = c("a", "b"))
y <- as.character(g)

object.size(g)
# 8000560 bytes
object.size(y)
# 16000160 bytes

一些注意事项:

  • 许多处理分类变量的 R 函数(tablesplit 等)在对它们进行任何其他操作之前将字符向量参数转换为因子。因此,实际上用分类变量做事情几乎总是涉及将一个因素提交到内存中。
  • 因素清楚地向用户传达变量是分类变量而不仅仅是字符串序列。

因此,有很多充分的理由喜欢因子,即使它们很短。