如何在 R 中使用 laf_open_fwf 读取固定宽度文件时管理流氓数据行
How to manage rogue data rows while reading fixed width files using laf_open_fwf in R
我正在尝试使用以下代码读取一个大文件:
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 行数据,这些数据都符合固定宽度定义;但在某些情况下,可能会有几行数据 "rogue" 因为它们不符合每列的固定宽度 - 某些列中的数据或者只是说一列可能更长或更短,当这个发生了,这个 reader 的输出完全被破坏了。
我认为解析器遇到的第一个流氓行之后解析的每个数据行都没有被正确解析。特别是当流氓数据行的最后一列有过多数据(比定义的宽度长)时会发生这种情况
因此,我们将不胜感激关于如何解决此问题的任何想法。
不幸的是,LaF
假设所有行都具有相同的长度。它使用行的宽度来快速跳到请求的行。要转到第 X 行,它知道从行的开头转到字节 (X - 1) * (sum(column_widths) + 1/2)
(1/2
取决于使用的 eof 行字符 \n
/\r\n
)。
唯一的解决办法是从文件中删除 'rogue' 行。下面我给出一个纯 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[,]
并且您可以检查其他文件以查看错误是什么。
我正在尝试使用以下代码读取一个大文件:
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 行数据,这些数据都符合固定宽度定义;但在某些情况下,可能会有几行数据 "rogue" 因为它们不符合每列的固定宽度 - 某些列中的数据或者只是说一列可能更长或更短,当这个发生了,这个 reader 的输出完全被破坏了。
我认为解析器遇到的第一个流氓行之后解析的每个数据行都没有被正确解析。特别是当流氓数据行的最后一列有过多数据(比定义的宽度长)时会发生这种情况
因此,我们将不胜感激关于如何解决此问题的任何想法。
不幸的是,LaF
假设所有行都具有相同的长度。它使用行的宽度来快速跳到请求的行。要转到第 X 行,它知道从行的开头转到字节 (X - 1) * (sum(column_widths) + 1/2)
(1/2
取决于使用的 eof 行字符 \n
/\r\n
)。
唯一的解决办法是从文件中删除 'rogue' 行。下面我给出一个纯 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[,]
并且您可以检查其他文件以查看错误是什么。