使用 read.table 阅读 R 中注释附近的行

Reading lines near comments in R with read.table

我正在阅读许多包含数据行的文本文件,顶部有几行 header 行包含数据信息,如下所示:

Test file
#
File information
1 2 3 4
#
a 2
b 4
c 6
d 8

我想从这个文件中单独读入各种信息。我可以像这样完成这个:

file <- read.table(txt, nrow = 1)
name <- read.table(txt, nrow = 1, skip = 2)
vals <- read.table(txt, nrow = 1, skip = 3)
data <- read.table(txt,           skip = 5)

由于两个空白注释行,我也可以这样读入数据:

file <- read.table(txt, nrow = 1)
name <- read.table(txt, nrow = 1, skip = 1)  # Skip changed from 2
vals <- read.table(txt, nrow = 1, skip = 3)
data <- read.table(txt,           skip = 4)  # Skip changed from 5

这很好,但是文本文件并不总是有相同数量的空白注释行;有时它们存在,有时它们不存在。如果我丢失了我的示例文本文件中的一个(或两个)注释行,我的两个解决方案都不会继续工作。

是否有更可靠的方法来读取 skip 变量永远不会计算注释行的文本文件?

(假设:在顶部的文件元数据之后,一旦数据开始,就没有更多的评论。)

(使用textConnection(...)是为了欺骗需要文件连接的函数来处理字符串。用文件名替换函数调用。)

一种技术是读取文件的前 n 行(某个数字 "guaranteed" 以包含所有 commented/non-data 行),找到最后一行,然后处理相应地 all-before 和 all-after:

txt <- "Test file
#
File information
1 2 3 4
#
a 2
b 4
c 6
d 8"
max_comment_lines <- 8
(dat <- readLines(textConnection(txt), n = max_comment_lines))
# [1] "Test file"        "#"                "File information" "1 2 3 4"         
# [5] "#"                "a 2"              "b 4"              "c 6"             
(skip <- max(grep("^\s*#", dat)))
# [1] 5

(顺便说一句:可能应该做一个检查以确保实际上有评论......这将 return integer(0) 否则, read* 函数不喜欢那作为一个论点。)

现在我们 "know" 最后找到的评论在第 5 行,我们可以使用前 4 行来获取 header 信息 ...

meta <- readLines(textConnection(txt), n = skip - 1)
meta <- meta[! grepl("^\s*#", meta) ] # remove the comment rows themselves
meta
# [1] "Test file"        "File information" "1 2 3 4"         

...并跳过 5 行以获取数据。

dat <- read.table(textConnection(txt), skip = skip)
str(dat)
# 'data.frame': 4 obs. of  2 variables:
#  $ V1: Factor w/ 4 levels "a","b","c","d": 1 2 3 4
#  $ V2: int  2 4 6 8