【问题标题】:Read lines by number from a large file从大文件中按行数读取
【发布时间】:2011-11-01 16:12:15
【问题描述】:

我有一个包含 1500 万行的文件(不适合内存)。我还有一个小的行号向量 - 我要提取的行。

我怎样才能一次读出这些行?

我希望有一个 C 函数可以一次性完成。

【问题讨论】:

    标签: r large-files line-numbers


    【解决方案1】:

    诀窍是使用连接并在read.table之前打开它:

    con<-file('filename')
    open(con)
    
    read.table(con,skip=5,nrow=1) #6-th line
    read.table(con,skip=20,nrow=1) #27-th line
    ...
    close(con)
    

    你也可以试试scan,它速度更快,控制力更强。

    【讨论】:

    • 绝对使用scanreadLines 来提高速度。 read.table 对数据类型、维度等进行了大量检查。最好不要将 c 用作 R 中的变量,因为它是最常用的函数之一(连接)。
    • 所以这只会从磁盘读取文件一次?如果在skip=5 之前调用skip=20,read.table 或scan 会如何表现?
    • @Aleksandr 这很简单;第一个read.table 将消耗连接中的skip+nrow 行,下一个read.table 将从这一点开始。以此类推。
    【解决方案2】:

    如果是二进制文件

    这里有一些讨论: Reading in only part of a Stata .DTA file in R

    如果是 CSV 或其他文本文件

    如果它们是连续的并且位于文件的顶部,只需使用 ,nrows 参数到 read.csv 或任何 read.table 系列。如果没有,您可以结合,nrows,skip 参数重复调用read.csv(每次调用读取新行或一组连续行),然后将结果一起rbind

    【讨论】:

    • 可以一次性完成吗?
    • @Aleksandr 绝对。但是read.table 似乎不是这样写的。如果您查看read.table 的源代码,它似乎不会太难修改。也许其他人会对执行此操作的现有功能有更好的答案。
    【解决方案3】:

    如果您的文件有固定的行长,那么您可以使用“seek”跳转到任何字符位置。因此,只需为您想要的每个 N 跳转到 N * line_length,然后读取一行。

    但是,来自 R 文档:

     Use of seek on Windows is discouraged.  We have found so many
     errors in the Windows implementation of file positioning that
     users are advised to use it only at their own risk, and asked not
     to waste the R developers' time with bug reports on Windows'
     deficiencies.
    

    你也可以在C中使用标准C库中的'seek',但不知道上面的警告是否也适用!

    【讨论】:

    • 大声笑@“要求不要浪费 R 开发人员的时间来报告 Windows 缺陷”哈哈。
    【解决方案4】:

    在获得 R 解决方案/答案之前,我已经在 Ruby 中完成了:

    #!/usr/bin/env ruby
    
    NUM_SEQS = 14024829
    
    linenumbers = (1..10).collect{(rand * NUM_SEQS).to_i}
    
    File.open("./data/uniprot_2011_02.tab") do |f|
      while line = f.gets
        print line if linenumbers.include? f.lineno 
      end
    end
    

    运行速度快(只要我的存储可以读取文件)。

    【讨论】:

    • 我不知道为什么这被否决了。鉴于可以从 R 中轻松调用 Ruby,例如 r-bloggers.com/calling-ruby-perl-or-python-from-r ,以及从 Ruby 中调用 R 的类似性,人们不应该回避使用最简单的解决方案。
    • 嗯,当然,您可以使用 [beakernotebook.com] 并在 C++ 中完成。但是,如果你能在 R 中找到同样好的,甚至慢 10% 的本机解决方案,我会坚持下去,除非你正在编写一次性代码。否则每个阅读代码的人都必须了解基本的 Ruby。否则,您无法将代码移植到另一个系统而不担心兼容性。可能存在安全问题等等等等。在没有必要时调用另一个进程通常不是一个好主意。我会说,最好只对问题添加评论(+链接)
    • 好吧,如果您要求一种语言的解决方案并以另一种语言提供解决方案,请考虑至少提供额外的代码以从另一种语言调用一种语言。
    【解决方案5】:

    我根据here 的讨论编写了一个解决方案。

    scan(filename,what=list(NULL),sep='\n',blank.lines.skip = F)
    

    这只会显示行数,但不会读取任何内容。如果你真的想跳过空行,你可以将最后一个参数设置为 TRUE。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2018-07-06
      • 2015-11-26
      • 2019-02-28
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2019-10-05
      • 2012-01-22
      相关资源
      最近更新 更多