为什么在R中更改stringsAsFactors会改变文件大小?

时间:2015-12-17 14:50:50

标签: r

我已经从PostgreSQL数据库中提取了一组数据,以便在R中使用它。在进行操作时,我不断被某些领域的因素绊倒,我不想要这些因素。所以,我回到了用于提取数据的代码,并确保options(stringsAsFactors = FALSE)已设置。

存储拉取数据的原始.RData文件(五个表,加上存储数据提取时间的变量)大约为800MB。更新版本,其中字符串未存储为因子,超过2GB。除了将stringsAsFactors设置为false之外,数据库内或代码中没有任何变化。

我最初的怀疑是因子级别对于存储文本更有效,因为实际文本将作为级别存储一次,然后每个值将被分配到一个级别。但我不认为这是对的 - 我的理解是R 中的因素是字符数据,结构在顶部。因此,在这种情况下,我认为文件大小不会有明显的差异。

所以,我的问题:为什么将stringsAsFactorsTRUE更改为FALSE会以如此大的方式更改结果数据的大小?

1 个答案:

答案 0 :(得分:1)

将问题中的评论合并为答案。

前面的底线: R因子是带附加标签的数字向量,它们使用字符操作和比较。这与SAS不同,SAS通过将独立因子应用于数值变量,以及使用数值运算和比较来创建类别。

从广义上讲,我最初怀疑的因素是分配给设置文本字符串的数值是正确的。 SAS和R如何处理这个问题之间存在一些差异,这是我提问的原因。

简而言之,SAS允许您创建自定义格式并将其应用于数字数据。因此,如果您有存储在数字变量中的分类数据(例如,将比赛分类为数字类别),则可以在使用字符串显示输出时保持该变量完整。

考虑SAS示例:

DATA sample;
    INPUT id race;
    DATALINES;
    1 1
    2 1
    3 2
    4 3
    5 1
    6 2
    7 4
    8 3
    9 1
    ;
RUN;

PROC FORMAT;
    VALUE raceft 1 = 'White'
                 2 = 'Black'
                 3 = 'Asian'
                 4 = 'Other';
RUN;

PROC PRINT DATA=sample;
    FORMAT race raceft.;
RUN;

输出:

Obs    id    race
 1      1    White
 2      2    White
 3      3    Black
 4      4    Asian
 5      5    White
 6      6    Black
 7      7    Other
 8      8    Asian
 9      9    White

但是,在此示例中,变量race仍为数字。针对它的SAS操作使用数字类别和比较操作。例如,选择所有白人将使用race = 1操作完成。

相反,R会将此数据存储为一个因素。请考虑以下事项。

sample <- data.frame(id = c(1:9),
                     race = c(1,1,2,3,1,2,4,3,1))
sample$race <- factor(x = sample$race,
                      levels = c(1:4),
                      labels = c("White","Black","Asian","Other"))

> sample
  id  race
1  1 White
2  2 White
3  3 Black
4  4 Asian
5  5 White
6  6 Black
7  7 Other
8  8 Asian
9  9 White

在这种情况下,变量race现在属于类factor,R使用字符比较和操作。例如,选择此中的所有白人将使用某种race = "White"操作来完成。

尽管R对因子使用字符操作,但数据实际上并不存储为字符变量。因素的结构是:

> dput(sample$race)
structure(c(1L, 1L, 2L, 3L, 1L, 2L, 4L, 3L, 1L), .Label = c("White","Black", "Asian", "Other"), class = "factor")

这与factor的文档一致,其中指出:

  

factor返回类"factor"的对象,该对象具有一组整数   使用模式"levels"的{​​{1}}属性对x的长度进行编码   唯一的character条目。如果参数(!anyDuplicated(.))为真(或   使用ordered)结果具有类ordered()

因此,R实际上将因子存储为数值,附带标签。这样做可以减少存储许多记录时所需的存储空间,这些记录会占用少量的离散值。但是,尽管基础值是数字,但在处理因子而不是数字因子时,R使用字符运算符。