我在这里记录了读取定宽文件在R中的替代方法列表,并提供了一些速度最快的基准测试结果。
我的首选方法是将fread
与stringi
结合使用;这是最快的方法之一,并具有作为data.table
存储数据的附加优点(依我之见):
library(data.table)
library(stringi)
col_ends <-
list(beg = c(1, 10, 15, 19, 23, 28, 32, 36,
41, 45, 49, 54, 58),
end = c(9, 14, 18, 22, 27, 31, 35,
40, 44, 48, 53, 57, 61))
data = fread(
"http://www.cpc.ncep.noaa.gov/data/indices/wksst8110.for",
header = FALSE, skip = 4L, sep = NULL
)[, lapply(1:(length(col_ends$beg)),
function(ii)
stri_sub(V1, col_ends$beg[ii], col_ends$end[ii]))
][ , paste0("V", c(2, 5, 8, 11)) := NULL]
请注意,
fread
会自动剥离前后的空格--有时这是不希望的,此时请设置
strip.white = FALSE
。
我们也可以通过以下方式使用列宽向量
ww
来开始操作:
ww <- c(9, 5, 4, 4, 5, 4, 4, 5, 4, 4, 5, 4, 4)
nd <- cumsum(ww)
col_ends <-
list(beg = c(1, nd[-length(nd)]+1L),
end = nd)
我们可以使用负索引更加健壮地选择要排除的列,例如:
col_ends <-
list(beg = c(1, -10, 15, 19, -23, 28, 32, -36,
41, 45, -49, 54, 58),
end = c(9, 14, 18, 22, 27, 31, 35,
40, 44, 48, 53, 57, 61))
然后将col_ends$beg[ii]
替换为abs(col_ends$beg[ii])
,在下一行中:
paste0("V", which(col_ends$beg < 0))
最后,如果您希望列名也能够被程序读取,您可以使用
readLines
进行清理:
cols <-
gsub("\\s", "",
sapply(1:(length(col_ends$beg)),
function(ii)
stri_sub(readLines(URL, n = 4L)[4L],
col_ends$beg[ii]+1L,
col_ends$end[ii]+1L)))
cols <- cols[cols != ""]
(请注意,将此步骤与
fread
结合使用需要创建表的副本以删除标题行,因此对于大型数据集而言效率低下)
read.fwf
以读取固定宽度格式的数据。 - Paul Hiemstra