防止fread()中的列类推断

时间:2015-04-07 18:58:13

标签: r data.table read.table

fread是否有办法模仿read.table的行为,其中变量的class由读入的数据设置。

我有数据,主要数据下面有一些注释。当我使用fread读取数据时,列将转换为字符。但是,通过在read.table中设置nrow,我可以停止此行为。这有可能在恐惧中。 (我宁愿不改变原始数据或修改副本)。感谢

一个例子

d <- data.frame(x=c(1:100, NA, NA, "fff"), y=c(1:100, NA,NA,NA)) 
write.csv(d, "test.csv",  row.names=F)

in_d <- read.csv("test.csv", nrow=100, header=T)
in_dt <- data.table::fread("test.csv", nrow=100)

哪个产生

> str(in_d)
'data.frame':   100 obs. of  2 variables:
 $ x: int  1 2 3 4 5 6 7 8 9 10 ...
 $ y: int  1 2 3 4 5 6 7 8 9 10 ...
> str(in_dt)
Classes ‘data.table’ and 'data.frame':  100 obs. of  2 variables:
 $ x: chr  "1" "2" "3" "4" ...
 $ y: int  1 2 3 4 5 6 7 8 9 10 ...
 - attr(*, ".internal.selfref")=<externalptr>

作为一种解决方法,我认为我可以使用read.table读取一行,获取课程并设置colClasses,但我很误解。

cl <- read.csv("test.csv", nrow=1,  header=T)
cols <- unname(sapply(cl, class))
in_dt <- data.table::fread("test.csv", nrow=100, colClasses=cols)
str(in_dt)

使用Windows8.1 R版本3.1.2(2014-10-31) 平台:x86_64-w64-mingw32 / x64(64位)

2 个答案:

答案 0 :(得分:18)

选项1:使用系统命令

fread()允许在其第一个参数中使用系统命令。我们可以用它来删除文件第一列中的引号。

indt <- data.table::fread("cat test.csv | tr -d '\"'", nrows = 100)
str(indt)
# Classes ‘data.table’ and 'data.frame':    100 obs. of  2 variables:
#  $ x: int  1 2 3 4 5 6 7 8 9 10 ...
#  $ y: int  1 2 3 4 5 6 7 8 9 10 ...
#  - attr(*, ".internal.selfref")=<externalptr> 

系统命令 cat test.csv | tr -d '\"' 解释:

  • cat test.csv将文件读取到标准输出
  • |是一个管道,使用上一个命令的输出作为下一个命令的输入
  • tr -d '\"'从当前输入中删除(-d)所有出现的双引号('\"'

选项2:阅读后强制

由于选项1似乎无法在您的系统上运行,因此另一种可能性是按原样读取文件,但将x列转换为type.convert()

library(data.table)
indt2 <- fread("test.csv", nrows = 100)[, x := type.convert(x)]
str(indt2)
# Classes ‘data.table’ and 'data.frame':    100 obs. of  2 variables:
#  $ x: int  1 2 3 4 5 6 7 8 9 10 ...
#  $ y: int  1 2 3 4 5 6 7 8 9 10 ...
#  - attr(*, ".internal.selfref")=<externalptr> 

旁注:我通常更喜欢使用type.convert()而不是as.numeric()来避免强制引入的&#34; NAs&#34; 在某些情况下会触发警告。例如,

x <- c("1", "4", "NA", "6")
as.numeric(x)
# [1]  1  4 NA  6
# Warning message:
# NAs introduced by coercion 
type.convert(x)
# [1]  1  4 NA  6

但当然你也可以使用as.numeric()


注意:此答案假定为data.table dev v1.9.5

答案 1 :(得分:-2)

好的,客户是abusing CSV format故意将尾随字符串行写入整数列,但没有那些以comment.char(#)开头的行。

然后你会以某种方式期望你可以覆盖fread()的类型推断来读取它们作为整数,通过使用nrow尝试将其限制为仅查看整数行。 read.csv(..., nrow)会接受这一点,但fread()始终使用所有行进行类型推断(而不仅仅是nrow, skip, header指定的行),即使它们以comment.char开头(这是一个bug) )。

  1. 听起来像滥用CSV。您的评论行应添加#
  2. 是的,fread()需要修复/增强才能忽略类型推断的注释行。
  3. 目前,您可以通过对读入的数据表进行后期处理来解决fread()
  4. 是否应该更改fread()以支持您想要的行为是有争议的:使用nrows来限制暴露给类型推断的内容。它可能会修复你的(非常独特的)案例并打破其他案件。
  5. 我不明白为什么你(编辑:客户)无法将您的评论写入单独的.txt / README /数据字典文件以伴随.csv。使用单独的数据字典文件的做法非常成熟。 我从未见过有人这样做过CSV文件。至少将注释移到标题上,而不是页脚。