如何在 R 中使用 laf_open_fwf 读取固定宽度文件时管理恶意数据行
Posted
技术标签:
【中文标题】如何在 R 中使用 laf_open_fwf 读取固定宽度文件时管理恶意数据行【英文标题】:How to manage rogue data rows while reading fixed width files using laf_open_fwf in R 【发布时间】:2016-04-28 12:01:06 【问题描述】:我正在尝试使用以下代码读取一个大文件:
laf <- laf_open_fwf(paste(input$dir,"/",filename,sep=""), column_widths = col_width,
column_types=rep("character",length(col_width)),
column_names = column_names)
性能不错,但我的问题是,假设文件有大约 100,000 行数据,这些数据都符合固定宽度定义;但在某些情况下,可能会有几行“流氓”数据,因为它们不符合每列的固定宽度 - 某些列中的数据,或者只是说一列可能更长或更短,当这种情况发生时,这个阅读器的输出完全被破坏了。
我认为在解析器遇到的第一条流氓行之后解析的每条数据行都没有正确解析。尤其是当流氓数据行的最后一列有过多数据(比为其定义的宽度长)时会发生这种情况
因此,我们将不胜感激有关如何解决此问题的任何想法。
【问题讨论】:
您可能需要使用readLines()
并自己解析数据。
是的,你是对的 - 我遵循了这个逻辑,我现在拥有所有流氓记录和正确记录的行号 - 但 laf_open_fwf 似乎可以通过打开与文件的连接来工作 - 所以我需要只有正确数据的文件。或者有没有一种方法可以指定解析器只读取选定的数据行?
我看不到。如果您可以使用一些 unix 实用程序来 grep 这些行并摆脱它们,则最简单。
是的,复杂之处在于应用程序的 UI 有两个选项卡,一个选项卡显示所有正确记录,另一个选项卡显示所有流氓记录,所以我需要两组数据
我可以将它们读入数据帧并识别记录长度大于预期最大长度的流氓记录。但是 laf 也会将多余的字符推到导致问题的下一行。
【参考方案1】:
不幸的是,LaF
假定所有行的长度相同。它使用行的宽度快速跳到请求的行。要转到第 X 行,它知道从行首转到字节 (X - 1) * (sum(column_widths) + 1/2)
(1/2
取决于使用的 eof 行字符 \n
/\r\n
)。
唯一的解决方案是从文件中删除“流氓”行。下面我给出一个纯 R 示例来说明如何做到这一点。它相当快。
生成带有 ~2% 'rogue' 行的示例文件:
lines <- c("abcde3.14", "efghi-123", "abcdef2.11")
lines <- sample(lines, 1E6, prob = c(0.44, 0.44, 0.02), replace=TRUE)
writeLines(lines, "test.dat")
以块的形式读取文件,将具有正确长度的行写入一个连接,将其他行写入另一个连接。通过打开循环外的连接并保持它们打开,这是相当快的:
widths <- c(5,4)
types <- c("string", "numeric")
names <- c("a", "b")
library(LaF)
con <- file("test.dat", "rt")
ok <- file("ok.dat", "wt")
notok <- file("notok.dat", "wt")
while (TRUE)
l <- readLines(con, n = 1E5) # increase n for faster reading; used 1E5 as example
if (length(l) == 0) break;
s <- nchar(l) == sum(widths)
writeLines(l[s], con = ok)
writeLines(l[!s], con = notok)
close(notok)
close(ok)
close(con)
然后可以通过LaF
解析具有正确行的文件:
laf <- laf_open_fwf("ok.dat", column_types = types, column_names = names,
column_widths = widths)
laf[,]
您可以检查其他文件以查看错误所在。
【讨论】:
以上是关于如何在 R 中使用 laf_open_fwf 读取固定宽度文件时管理恶意数据行的主要内容,如果未能解决你的问题,请参考以下文章
R读取大型数据集内存不足如何解决,如果利用Linux有啥有效方法吗?