有效读取数据文件,其中列按行排列

时间:2019-07-17 01:45:37

标签: r data.table

假设我有一个类似于csv的数据文件,如下所示,其中数据的“列”按行排列:

col1,1.1,1.2,3.3
col2,A,B,C
col3,TRUE,TRUE,FALSE
col4,1,2,3
col5,1,2,3
col6,1,2,3
col7,1,2,3
col8,1,2,3
col9,1,2,3
col10,1,2,3
col11,1,2,3
col12,1,2,3
col13,1,2,3
col14,1,2,3
col15,1,2,3

我如何有效地将此类文件读入R。理想情况下,我想要一个类似于data.table::fread的可扩展,快速的解决方案,该解决方案可以自动确定数据类型。

对于上述示例(如果它位于名为test.csv的文件中),我可以执行以下操作:

library(data.table)    
dt = strsplit(read_lines('test.csv'),',') %>%
  lapply(function(r) fread(paste0(r, collapse ='\n'))) %>%
  as.data.table()

str(dt)
# Classes ‘data.table’ and 'data.frame':    3 obs. of  15 variables:
# $ col1 : num  1.1 1.2 3.3
# $ col2 : chr  "A" "B" "C"
# $ col3 : logi  TRUE TRUE FALSE
# $ col4 : int  1 2 3
# $ col5 : int  1 2 3
# $ col6 : int  1 2 3
# $ col7 : int  1 2 3
# $ col8 : int  1 2 3
# $ col9 : int  1 2 3
# $ col10: int  1 2 3
# $ col11: int  1 2 3
# $ col12: int  1 2 3
# $ col13: int  1 2 3
# $ col14: int  1 2 3
# $ col15: int  1 2 3
# - attr(*, ".internal.selfref")=<externalptr> 
#

但是这有一些缺点。除了损失读取速度和效率,并要求事先知道分隔符外,它也不是很可靠。

例如,一行

col4,"hello, world","hello, world","hello, world"

会破坏它,因为strsplit不知道逗号是分隔符还是字符串的一部分。

缺少数据也是有问题的:

col5,1,2,

产生

  

警告消息:在data.table(list(col1 = c(1.1,1.2,3.3)),   list(col2 = c(“ A”,:项目5的大小为2,但最大大小为3   (已回收,剩余1件物品)

是否有更好的方式读取此类数据?

1 个答案:

答案 0 :(得分:2)

一个更简单的选择是在读取数据集之后进行转置,然后执行type.convert

dat <- read.csv("test.csv", header = FALSE, stringsAsFactors = FALSE)
dat2 <- type.convert(setNames(as.data.frame(t(dat[-1]),
        stringsAsFactors = FALSE), dat$V1), as.is = TRUE)
row.names(dat2) <- NULL

str(dat2)
#'data.frame':  3 obs. of  15 variables:
# $ col1 : num  1.1 1.2 3.3
# $ col2 : chr  "A" "B" "C"
# $ col3 : logi  TRUE TRUE FALSE
# $ col4 : int  1 2 3
# $ col5 : int  1 2 3
# $ col6 : int  1 2 3
# $ col7 : int  1 2 3
# $ col8 : int  1 2 3
# $ col9 : int  1 2 3
# $ col10: int  1 2 3
# $ col11: int  1 2 3
# $ col12: int  1 2 3
# $ col13: int  1 2 3
# $ col14: int  1 2 3
# $ col15: int  1 2 3

或者我们用fread阅读,然后进行相同的转置

library(data.table)
dt <- fread("test.csv", header = FALSE)
type.convert(setNames(as.data.frame(t(dt[, -1, with = FALSE]), 
       stringsAsFactors = FALSE), dt[[1]], as.is = TRUE)

或按照@Frank的建议

fread("test.csv")[, setnames(transpose(.SD[,-1]), .SD[[1]])][, 
        lapply(.SD, type.convert)]