data.table::fread 的 stringsAsFactors=TRUE 参数不会将字符列转换为因子类型 - 解决方法是什么?

data.table::fread's stringsAsFactors=TRUE argument doesn't convert character columns to factor type - what's the workaround?

我知道这个问题已在多个地方提出,我已经尝试了几个小时来寻找可能的好的解决方案,但都失败了。这就是我问这个的原因。

所以,我有一个巨大的数据文件 (~5GB),我用 fread() 阅读了这个

library(data.table)
df<- fread('output.txt', sep = "|", stringsAsFactors = TRUE)
head(df, 5)
       age            income homeowner_status_desc marital_status_cd gender
1:         ,000 - ,999                                               
2: 35 - 44 ,000 - ,999                  Rent            Single      F
3:         ,000 - ,999                                               
4:                                                                         
5:         ,000 - ,999 
str(df)
Classes ‘data.table’ and 'data.frame':  999 obs. of  5 variables:
 $ age                  : chr  "" "35 - 44" "" "" ...
 $ income               : chr  ",000 - ,999" ",000 - ,999" ",000 - ,999" "" ...
 $ homeowner_status_desc: chr  "" "Rent" "" "" ...
 $ marital_status_cd    : chr  "" "Single" "" "" ...
 $ gender               : chr  "" "F" "" "" ...
 - attr(*, ".internal.selfref")=<externalptr> 

缺少数据(空白处)。在原始数据中,有很多列,因此我需要找到一种方法来在列包含字符串时生成列因子。谁能建议完成这项工作的最佳做​​法是什么?我正在考虑将其更改为数据框并执行此操作。但是在 data.table 时是否可以这样做?

这基本上是一条评论,但它很长,所以就到这里。

您可能想要使用 colClasses 来指定哪些列是因子。

如果您有很多列,我为简化而做的事情是使用我编写的以下函数:

abbr_to_colClass<-function(inits,counts){
  x<-substring(inits,1:nchar(inits),1:nchar(inits))
  types<-ifelse(x=="c","character",
                ifelse(x=="f","factor",
                       ifelse(x=="i","integer",
                              "numeric")))
  rep(types,substring(counts,1:nchar(counts),1:nchar(counts)))
}

假设您有一个 .csv 列 类:

character 3
factor    2
integer   1
numeric   5
character 6

那你可以用我的函数来设置

colClasses=abbr_to_colClass("cfinc","32156")

如果连续有一种类型的长字符串,这将特别节省 space。

(我知道这不是最强大的功能,但是当有很多字段要读取时,它多次为我提供了很好的服务)

我制作了一个小的 csv 文件,我可以确认相同的行为,其中 stringsAsFactors=TRUE 不会导致因子列。另外指定 colClasses 作为因素似乎也不起作用。

如果你在 fread 之后 运行 它会将你所有的字符列转换为因子

for (j in which(sapply(df, class)=='character')) set(df, i=NULL, j=j, value=as.factor(df[[j]]))

试试新的 readr 包,它已经过优化,速度提高了 10 倍并且不会泄漏内存。您现在可以指定 col_types 参数,而不是 stringsAsFactors,您可以在其中指定 collector(自定义解析器函数)。查看文档,尤其是。 col_factor/parse_factor.

require(readr)
read_csv(..., col_types=...)

刚刚在 v 1.9.6+

中为 fread 实现了 stringsAsFactors 参数

来自NEWS

  1. Implemented stringsAsFactors argument for fread(). When TRUE, character columns are converted to factors. Default is FALSE. Thanks to Artem Klevtsov for filing #501, and to @hmi2015 for .