【问题标题】:How to read a txt file that contains different tables in it如何读取其中包含不同表的 txt 文件
【发布时间】:2021-07-06 12:20:31
【问题描述】:

我必须在 R 中收集数据,这些数据以 xls 格式提供给我,但是当我用 Excel 打开它时,它说扩展名和格式不匹配,文件建议我应该将其另存为.txt 文件。

我必须使用的文件通常包含 3 个部分,其中包含不同的表,它们具有不同的大小和列名。这些部分由方括号之间的标题宣布。这是我文件的simplified version

我只对名为“[DATA]”的第三部分感兴趣。到目前为止,我已手动将其保存为 xlsx 文件,并以我的方式使用我感兴趣的数据,即使用 read_excel。在阅读了 R 中的整张表格后,我收集了标题“[DATA]”所在的行(它可能因文件而异,我无法像 readLines 中那样选择行号),然后我可以选择下面的表格列名(T、时间、张力等)作为我的新数据框的列名。我希望能够从 txt 文件开始做类似的事情,因为我有很多文件要处理,而且它们的格式完全相同。 我尝试了几个函数来将文件读取为.txt,比如 1A = data.table::fread(file, header = F, fill=F, sep = '\t') 2)A = read.delim(file) 3)A = data.frame(readLines(file)) 4)A = read.table(file)

  1. 它从 SETUP 中保存第一个表并提前停止,并显示此错误消息“在第 25 行提前停止。预期有 24 个字段但找到了 1 个。考虑 fill=TRUE 和 comment.char=。第一个丢弃的非空行:>" .如果我输入 fill = TRUE,我会得到与 3 相同的结果。

  2. 它将所有单元格组成一个大列,逐行逐个单元格。从那里重新排列表格中的数据变得很困难。

  3. 它再次构成一个大列,但文件的每一行都是数据框中的一个单元格,单元格的内容是所有数字的字符串,由 \t 分隔。第 8 行示例:experiment1\group1\t0\t7200\t0.001\t"

  4. 我收到此错误消息:扫描错误(文件 = 文件,内容 = 内容,s​​ep = sep,quote = quote,dec = dec,: 第 4 行没有 2 个元素

我不知道这些函数中的哪一个最适合这项任务。

注意:错误消息中显示的数字可能与我在示例中得到的不同,但我什至没有收到示例中的错误消息(当我制作它时,Excel 要求我放一个撇号在单元格中,因此“减号”不会被视为公式,所以我这样做了。然后我将文件保存在 txt 和 xls 中,甚至将 xls 扩展名添加到 txt 文件中以创建扩展名的不连贯性,如我的原始文件。它在任何情况下都有效。)

感谢您的帮助!

【问题讨论】:

    标签: r excel format


    【解决方案1】:

    您说的是文本文件并显示电子表格,所以我将在多表 CSV 文件上进行演示:

    csvtext <- '[SETUP]
    ExpName:
    GroupName:
    ,,
    Experiment,Group,Voltage
    1,1,1
    2,2,2
    3,3,3
    ,,
    [RESULT]
    Group,Dev,V3
    1,1,1
    3,3,3
    4,4,4
    ,,
    [Data]
    "mpg","cyl","disp"
    21,6,160
    21,6,160
    22.8,4,108
    '
    

    以文本形式读入:

    # you may use something like
    # rawtext <- readLines("path/to/file.csv")
    rawtext <- readLines(textConnection(csvtext))
    str(rawtext)
    #  chr [1:21] "[SETUP]" "ExpName:" "GroupName:" ",," "Experiment,Group,Voltage" "1,1,1" "2,2,2" "3,3,3" ",," "[RESULT]" ...
    

    我们现在可以根据“空”行拆分数据,然后删除这些空行:

    spltext <- split(rawtext, cumsum(!grepl("[^,\\s]", rawtext)))
    spltext <- lapply(spltext, function(z) if (grepl("[^,\\s]", z[1])) z else z[-1])
    str(spltext)
    # List of 5
    #  $ 0: chr [1:3] "[SETUP]" "ExpName:" "GroupName:"
    #  $ 1: chr [1:4] "Experiment,Group,Voltage" "1,1,1" "2,2,2" "3,3,3"
    #  $ 2: chr [1:5] "[RESULT]" "Group,Dev,V3" "1,1,1" "3,3,3" ...
    #  $ 3: chr [1:5] "[Data]" "\"mpg\",\"cyl\",\"disp\"" "21,6,160" "21,6,160" ...
    #  $ 4: chr(0) 
    

    (请注意,$ 0 表示 name"0" 而不是 0,因此我们稍后需要使用字符串编号进行索引。)

    从这里开始,既然你只想要[Data] 部分,那么

    read.csv(text = spltext[["3"]][-1])
    #    mpg cyl disp
    # 1 21.0   6  160
    # 2 21.0   6  160
    # 3 22.8   4  108
    

    【讨论】:

    • 感谢您的回答!我一步一步地尝试了您的示例,似乎 R 将“mpg”、“cyl”、“disp”读为一个单元格而不是列名。我得到“比列名更多的列”。这就是我在没有标题的情况下得到的:V1 V2 V3 1 "mpg","cyl","disp" NA NA 2 21 6 160 3 21 6 160 4 22.8 4 108
    • 我也尝试了我的示例数据,但我遇到了同样的问题 [2]: i.stack.imgur.com/QAJU3.png 。注意:为了让它工作,我使用 [^,\\s, \t] 而不是 [^,\\s] 因为分隔符是 \t 或 \t\t\t...\t 而不是逗号.
    • 如果您更新分隔符以包含\t,它会起作用吗?那太棒了!请接受答案。
    • 仅供参考,您的模式中不需要两个逗号。它是regex,它是一个字符组,这意味着[] 中的任何字符都可以使用;所以!grepl("[^,\\s\t]", rawtext) 也可以。就此而言,您可能不需要,,因为它是制表符分隔的(从问题中不明显)。
    【解决方案2】:

    我让它在我的任何文件(txt)上工作:

    rawtext

    #分隔部分,它们之间有一个空行 spltext

    #删除由以前的空行编码的单元格 \t spltext

    #索引为3的列是包含DATA表的那一列 data=read.delim(text = base[["3"]][-1], header= T, check.names=F) #check.names= F 不影响标题

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2017-10-05
      • 2020-09-12
      • 1970-01-01
      相关资源
      最近更新 更多