我已经从PostgreSQL数据库中提取了一组数据,以便在R中使用它。在进行操作时,我不断被某些领域的因素绊倒,我不想要这些因素。所以,我回到了用于提取数据的代码,并确保options(stringsAsFactors = FALSE)
已设置。
存储拉取数据的原始.RData
文件(五个表,加上存储数据提取时间的变量)大约为800MB。更新版本,其中字符串未存储为因子,超过2GB。除了将stringsAsFactors
设置为false之外,数据库内或代码中没有任何变化。
我最初的怀疑是因子级别对于存储文本更有效,因为实际文本将作为级别存储一次,然后每个值将被分配到一个级别。但我不认为这是对的 - 我的理解是R 中的因素是字符数据,结构在顶部。因此,在这种情况下,我认为文件大小不会有明显的差异。
所以,我的问题:为什么将stringsAsFactors
从TRUE
更改为FALSE
会以如此大的方式更改结果数据的大小?
答案 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使用字符运算符。