从单个文件中提取表

时间:2017-01-07 15:11:01

标签: r

我正在尝试从R中的单个文件中提取多个表。我的文件包含具有相同数量的变量但具有可变数量的记录的表。我想只提取表(数字)并将它们转移到单独的文件中。在表之间有4行(空行,运行:nr,变量名,单位),我想摆脱它们。在每个空行处打破的替代方案对我来说也是一个很好的解决方案,但我还没有设法做到这一点。下面我提供了文件示例 - 我的真实文件包含多个运行(表),每个运行超过30个变量和150-300个记录。 非常感谢你的帮助!

示例:

> data <- readLines(textConnection("
              + MODEL OUTPUT
              +
              + Run: 1
              + V1  V2 V3
              +        mm
              + 20  2  2.0
              + 21  2  1.5
              + 22  2  3.5
              +
              + Run: 2
              + V1 V2 V3
              +       mm
              + 1  1  1.5
              + 2  1  2.5
              +
              + Run: 3
              + V1 V2 V3
              +       mm
              + 11  5  1.5
              + 12  5  2.5                                
              + 13  5  1.0
              + 14  5  4.5"))

1 个答案:

答案 0 :(得分:0)

如果我们没有将此标记为重复,我会回答。您可以通过一些预处理来处理这个问题,然后cumsum来枚举文本的连续部分,最后read.table将这些部分作为表来阅读。

创建示例数据:

file_text <- readLines(textConnection("
    + MODEL OUTPUT
    +
      + Run: 1
    + V1  V2 V3
    +        mm
    + 20  2  2.0
    + 21  2  1.5
    + 22  2  3.5
    +
      + Run: 2
    + V1 V2 V3
    +       mm
    + 1  1  1.5
    + 2  1  2.5
    +
      + Run: 3
    + V1 V2 V3
    +       mm
    + 11  5  1.5
    + 12  5  2.5                                
    + 13  5  1.0
    + 14  5  4.5"))

预处理:消除MODEL OUTPUT,领先+,以及只有mm的行。

file_text = file_text[!grepl('MODEL OUTPUT', file_text)]
file_text = file_text[!grepl('Run: \\d+', file_text)]
file_text = sapply(file_text, sub, pattern = "^\\s*\\+", replacement = "")
file_text = file_text[!grepl('^\\s*mm\\s*$', file_text)]

识别空行 - 将这些段称为段之间的断点 - 然后按节对行进行编号。

is_break = unname(sapply(file_text, function(x) trimws(x) == ""))
section_id = unname(cumsum(is_break))
section_id
#  [1] 1 2 2 2 2 2 3 3 3 3 4 4 4 4 4 4

最后将文件文本拆分为多个部分并将其作为表格读取:

tabs = lapply(unique(section_id), function(i) {
  # the first line of a section will always be empty
  section_lines = file_text[section_id == i][-1]
  if (length(section_lines)) {
    # there's a section of text
    read.table(text = section_lines, header = TRUE)
  } else {
    # there were two consecutive section breaks, so after the first break
    # there's an empty 'section'
    NA
  }
})

结果是data.frames列表。根据需要,现在或更早地处理丢失的表。

tabs
# [[1]]
# [1] NA
# 
# [[2]]
#   V1 V2  V3
# 1 20  2 2.0
# 2 21  2 1.5
# 3 22  2 3.5
# 
# [[3]]
#   V1 V2  V3
# 1  1  1 1.5
# 2  2  1 2.5
# 
# [[4]]
#   V1 V2  V3
# 1 11  5 1.5
# 2 12  5 2.5
# 3 13  5 1.0
# 4 14  5 4.5
#