一种过滤文本文件的算法

时间:2011-01-07 18:50:05

标签: r import

想象一下,你有一个以下结构的.txt文件:

>>> header
>>> header
>>> header
K L M
200 0.1 1
201 0.8 1
202 0.01 3
...
800 0.4 2
>>> end of file
50 0.1 1
75 0.78 5
...

我想读取除>>>表示的行和>>> end of file行下面的行以外的所有数据。 到目前为止,我已使用read.table(comment.char = ">", skip = x, nrow = y)xy目前已修复)解决了这个问题。这将读取标头和>>> end of file之间的数据。

但是,我想让我的功能在行数上更加可塑。数据的值可能大于800,因此行数更多。

我可以scanreadLines该文件,看看哪一行对应>>> end of file并计算要读取的行数。你会用什么方法?

2 个答案:

答案 0 :(得分:11)

这是一种方法:

Lines <- readLines("foo.txt")
markers <- grepl(">", Lines)
want <- rle(markers)$lengths[1:2]
want <- seq.int(want[1] + 1, sum(want), by = 1)
read.table(textConnection(Lines[want]), sep = " ", header = TRUE)

给出了:

> read.table(textConnection(Lines[want]), sep = " ", header = TRUE)
    K    L M
1 200 0.10 1
2 201 0.80 1
3 202 0.01 3
4 800 0.40 2

在您提供的数据代码段中(在文件foo.txt中,并在删除...行后)。

答案 1 :(得分:11)

以下是两种方法。

1)readLine将文件行读入L并将skip设置为开头要跳过的行数,end.of.file为行号标记数据结尾的行。然后read.table命令使用这两个变量重新读取数据。

File <- "foo.txt"

L <- readLines(File)
skip <- grep("^.{0,2}[^>]", L)[1] - 1
end.of.file <- grep("^>>> end of file", L)

read.table(File, header = TRUE, skip = skip, nrow = end.of.file - skip - 2)

变体是使用textConnection代替File行中的read.table

read.table(textConnection(L), header = TRUE, 
   skip = skip, nrow = end.of.file - skip - 2)

2)另一种可能性是使用sed或awk / gawk。考虑这一行gawk程序。如果程序看到标记数据结尾的行,则程序退出;否则,如果该行以&gt;&gt;&gt;开头,它会跳过当前行如果这些都不发生,则打印出该行。我们可以通过gawk程序管道foo.txt并使用read.table读取它。

cat("/^>>> end of file/ { exit }; /^>>>/ { next }; 1\n", file = "foo.awk")
read.table(pipe('gawk -f foo.awk foo.txt'), header = TRUE)

这样做的一个变体是我们可以省略gawk程序的/^>>>/ {next};部分,该部分跳过开头的>>>行,并使用comment = ">" in the read.table`调用代替。