1

我正在尝试读入(并最终合并/链接/操作)一系列大(~300M)和非常大(~4G)的固定宽度文件,用于最终的回归、可视化等,并且遇到了一些障碍。

首先,文件本身的格式很奇怪——我猜是 SQL-y。此处引用了文件格式: https ://msdn.microsoft.com/en-us/library/ms191479.aspx 。它是固定宽度,但在该列经历完整的固定宽度之前,最后一列似乎(有时?)用 \r\n 切断。为了阅读它,我尝试了 laf_open_fwf 和 data.table::fread,但他们似乎都感到困惑。示例文件和相关的非 XML 格式描述符在此处。我什至无法通过那愚蠢的最后一栏正确阅读内容。这是该文件的示例:

1           1           7           7           ER
2           2           9           8           OI
3           54016       1988006     1953409     OI        
4           54017       1988014     1953415     ER        
5           54017       1988014     1953415     OB        

(但请注意,CR/LF 在这里是不可见的,问题在于它们的奇怪位置。请参阅上面的记事本 ++ 视图的 .txt 文件或 png 文件(我无法链接,低代表)的链接数据来证明该领域的问题。)

其次,文件大小是一个问题。我知道我有很多表操作要做,所以我很想看看 data.table ......但我也相信 data.table 将整个对象存储在 RAM 中,这将是有问题的。LaF 或 ffdf 或 sqlite 似乎是选项,虽然我是新手,但需要先处理这个文件格式问题。

一些问题得到了这个一般的想法,建议 LaF、ffbase 或 data.table 在下面......

读取固定宽度的大数据

在 R 中快速读取非常大的表作为数据框

加快R中固定宽度格式表的导入

...但似乎没有人(1)处理这种奇怪的固定宽度格式或(2)最终将数据移动到 data.tables 中,这似乎是我想先尝试的。我考虑过尝试将它们打开并重写为格式良好的 CSV,以便 data.table 可以处理它们(我通过 data.frames 并返回 csv 的愚蠢破解感觉荒谬且不可扩展,如下)。CSV 导出表明文件变得多么混乱,因为 laf 阅读器严格按字段长度而不是根据 /r/n 的位置进行调整......

目前我正在尝试类似下面的初学者。帮助,如果可能的话?

require("data.table", "LaF", "ffbase")
searchbasis.laf = laf_open_fwf("SEARCHBASIS.txt",
                               column_widths = c(12, 12, 12, 12, 10), 
                               column_names = c("SearchBasisID", "SearchID", "PersonID", "StopID", "Basis"),
                               column_types = rep("string",5),
                               trim = T)
# ^ The laf_open_fwf quietly "fails" because the last column doesn't always 
# have 10 chars, but sometimes ends short with /r/n after the element.
searchbasis.dt = as.data.table(as.data.frame(laf_to_ffdf(searchbasis.laf)))
write.csv(searchbasis.dt, file="SEARCHBASIS.csv")
# ^ To take a look at the file.  Confirms that the read from laf, transfer 
# to data.table is failing because of the last column issue.
4

2 回答 2

2

对于这个特定的文件:

form <- read.table("SEARCHBASIS_format.txt", as.is = TRUE, skip = 2)
x <- read.table("SEARCHBASIS.txt", col.names = form$V7, as.is = TRUE)

如果您有时有包含空格的字符串,您几乎肯定需要先在外部处理文件。

如果您打算阅读非常大的文件,我建议(假设您的路径上有 awk):

x <- setNames(data.table::fread("awk '{$1=$1}1' SEARCHBASIS.txt"), form$V7)

如果你想使用固定宽度,你可以使用:

x <- setNames(fread("gawk 'BEGIN {OFS = \"\t\"; FIELDWIDTHS = \"12 12 12 12 12\"} {for (i = 1; i<= NF; i++) {gsub(/ +$/, \"\", $i);}}1' SEARCHBASIS.txt"), form$V7)

您还可以从格式文件中提取宽度:

x <- setNames(fread(paste0("gawk 'BEGIN {OFS = \"\t\"; FIELDWIDTHS = \"", paste(form$V4, collapse = " "), "\"} {for (i = 1; i<= NF; i++) {gsub(/ +$/, \"\", $i);}}1' SEARCHBASIS.txt")), form$V7)

注意$1=$1强制 awk 重新评估字段,最后的 1 实际上是print. 我还假设您想从每个字段中删除尾随空格。

在 Windows 上,您需要在 R 中使用单引号并将命令中的单引号替换为 ",并将嵌套的双引号替换为 ""。所以上面的最后一个变为:

x <- setNames(fread(paste0('gawk \"BEGIN {OFS = ""\t""; FIELDWIDTHS = ""', paste(form$V4, collapse = " "), '""} {for (i = 1; i<= NF; i++) {gsub(/ +$/, """", $i);}}1" SEARCHBASIS.txt')), form$V7)

对于跨平台解决方案,您需要将 awk 脚本放在外部文件中:

剥离空间.awk

BEGIN {OFS="\t"} {for (i = 1; i<= NF; i++) {gsub(/ +$/, "", $i);}}1

R代码

x <- setNames(fread(paste0('gawk -v FIELDWIDTHS="', paste(form$V4, collapse = " "), '" -f stripSpace.awk SEARCHBASIS.txt')), form$V7)

在 Scientific Linux 6 和 Windows 8.1 上测试

于 2015-06-28T21:40:43.617 回答
2

通过最近的修复,fread()现在可以毫无问题地读取具有多个空格的行(v1.9.5+ devel),使用它的strip.white参数(=TRUE默认情况下):

require(data.table) # v1.9.5+
fread("1           1           7           7           ER
2           2           9           8           OI
3           54016       1988006     1953409     OI        
4           54017       1988014     1953415     ER        
5           54017       1988014     1953415     OB        
")
#    V1    V2      V3      V4 V5
# 1:  1     1       7       7 ER
# 2:  2     2       9       8 OI
# 3:  3 54016 1988006 1953409 OI
# 4:  4 54017 1988014 1953415 ER
# 5:  5 54017 1988014 1953415 OB

我希望这适用于您的情况。如果没有,请告诉我们,我们将看看是否可以在fread(). 升级到开发版本(请参阅我们项目页面上的安装说明)或等待下一个 CRAN 版本(如 v1.9.6)。

于 2015-09-17T00:23:34.807 回答