如何在R中跳过制表符分隔文件头之前的额外行?

3

我正在使用的软件生成具有可变行数的摘要信息后跟大量制表符分隔数据的日志文件。我正在尝试编写一个函数,将这些日志文件中的数据读取到数据框中,并忽略摘要信息。摘要信息从不包含制表符,因此以下函数有效:

read.parameters <- function(file.name, ...){
  lines <- scan(file.name, what="character", sep="\n")
  first.line <- min(grep("\\t", lines))
  return(read.delim(file.name, skip=first.line-1, ...))
}

然而,这些日志文件非常大,因此两次读取文件速度非常慢。肯定有更好的方法吧?
编辑后添加:
Marek建议使用textConnection对象。他在答案中提出的方法在处理大文件时会失败,但以下方法可行:
read.parameters <- function(file.name, ...){
  conn = file(file.name, "r")
  on.exit(close(conn))
  repeat{
    line = readLines(conn, 1)
    if (length(grep("\\t", line))) {
      pushBack(line, conn)
      break}}
  df <- read.delim(conn, ...)
  return(df)}
再次编辑: 感谢Marek对上述函数的进一步改进。

1
为了安全地关闭连接,您可以使用 on.exit 函数。在 conn=file(...) 之后添加一行 on.exit(close(conn))。然后当函数完成任务(正常或出现错误)时,连接将被关闭。否则,当您在 fileclose 之间遇到错误时,连接将保持打开状态。 - Marek
谢谢,技术不错。我已经更新了。 - Michael Dunn
2个回答

1

你不需要读两遍。在第一个结果上使用textConnection

read.parameters <- function(file.name, ...){
  lines <- scan(file.name, what="character", sep="\n") # you got "tmp.log" here, i suppose file.name should be
  first.line <- min(grep("\\t", lines))
  return(read.delim(textConnection(lines), skip=first.line-1, ...))
}

我已经修复了这个笔误。感谢您建议使用textConnection,尽管您提供的函数并没有生效。我认为我需要首先创建textConnection,然后在它上运行scan,最后使用pushBack将文件倒回。 - Michael Dunn
奇怪,我测试了一下用我的虚假数据可以运行。你是否得到了错误消息或者空结果? - Marek
示例:cat(c("ds","sdds","sddfsd","a\tb\tc","1\t2\t3","1\t2\t3"),file="test.txt", sep="\n") 然后 read.parameters("test.txt") 返回一个有3列2行的数据框。 - Marek
有趣。我可以确认它可以使用您的虚假数据,但是对于我的大型数据文件,R会停止响应,我不得不强制退出。但是受到您的建议的启发,我已经制作出一个可工作的版本(为了保留格式而添加到问题中)。 - Michael Dunn

0
如果您可以确定头信息不会超过N行,例如N = 200,则尝试:
scan(..., nlines = N)
这样您就不会重新读取超过N行的内容。

这是一个不错的方法,但我不能保证标题大小。我对使用文件指针的函数感到非常满意。 - Michael Dunn

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接