将txt文件转换为数据框

时间:2020-10-05 14:49:46

标签: r regex dataframe

我有一个txt文件,其中包含以下数据:

1 message («random_choice»)[5];
2 reply («принято»)[2][3];
3 regulate («random_choice»)[5];
4 Early reg («for instance»)[2][3][4];
4xx: Success (загрузка):
6 OK («fine»)[2][3];

我想将其转换为数据框,由三列ID,消息,注释组成。 我也想删除方括号中末尾不必要的数字。 并且ID列中的某些值也包含字符串(通常为xx)。在这些情况下,列必须为空。 因此,所需的结果必须如下所示:

ID      Message        Comment
1       message     random_choice
2       reply       принято
3       regulate    random_choice
4       Early reg   for instance
        Success     загрузка
6       OK          fine

我该怎么做?即使我尝试读取此txt文件,我也会收到奇怪的错误:

df <- read.table("data_received.txt", header = TRUE)

我得到的错误:

Error in read.table("data_received.txt", header = TRUE) : 
  more columns than column names

2 个答案:

答案 0 :(得分:4)

您可以为此使用strcapture

伪造数据,您很可能会txt <- readLines("data_received.txt")。 (由于我在Windows上的语言环境对那些字符串不友好,因此,假设它在您的系统上可以正常工作,我将用纯ascii代替。)

txt <- readLines(textConnection("1 message («random_choice»)[5];
# 2 reply («asdf»)[2][3];
# 3 regulate («random_choice»)[5];
# 4 Early reg («for instance»)[2][3][4];
# 4xx: Success (something):
# 6 OK («fine»)[2][3];"))

突破:

out <- strcapture("^(\\S+)\\s+([^(]+)\\s+\\((.*)\\).*$", txt, 
                  proto = data.frame(ID=0L, Message="", Comment=""))
# Warning in fun(mat[, i]) : NAs introduced by coercion
out
#   ID   Message         Comment
# 1  1   message «random_choice»
# 2  2     reply          «asdf»
# 3  3  regulate «random_choice»
# 4  4 Early reg  «for instance»
# 5 NA   Success       something
# 6  6        OK          «fine»

proto=参数指示生成什么类型​​的列。由于我设置了ID=0L,因此假设它是整数,因此任何不转换为整数的东西都将变成NA(满足您的第五行遗漏)。

对正则表达式的解释:

  • 通常:
    • *表示上一个字符(或字符类)为零或更多
    • +意味着一个或多个
    • ?(未使用,但仍然有用)表示零或一。
    • ^$分别表示字符串的开头和结尾(^中的[..]不同)
    • (...)是一个捕获组:未转义的括号内的所有内容均已存储,所有未丢弃的内容均被丢弃
    • [...]是一个字符组,任何字符都是一个匹配项;如果它是[^..],那么它将被倒置:除了列出的任何内容
    • [[...]]是一个字符类
  • ^(\\S+),以(^)个或多个(+)个非空格字符(\\S)开始;
  • \\s+一个或多个空格字符(\\s)(已舍弃);
  • ([^(]+)一个或多个不是左括号的字符;
  • \\((.*)\\)$一个文字左括号(\\(),然后零个或多个任何内容.*),全部到达文字右括号(\\))和字符串结尾($)的方式。

应注意,\\s\\S是非POSIX regex字符,通常建议将[^[:space:]]用于\\S(不带空格),并且[[:space:]]的{​​{1}}。这些是等效的,但我最初使用代码高尔夫球。替换后,它看起来像

\\s

答案 1 :(得分:1)

我们可以使用 {unglue} 。在这里,我们看到您有两种模式,一种包含“«”和ID,另一种则没有。 {unglue} 将使用第一个匹配的模式。任何{foo}{}表达式都与正则表达式“。*?”匹配,并且data.frame是由放在方括号之间的名称构建的。

txt <- c(
  "1 message («random_choice»)[5];", "2 reply («asdf»)[2][3];", 
  "3 regulate («random_choice»)[5];", "4 Early reg («for instance»)[2][3][4];", 
  "4xx: Success (something):", "6 OK («fine»)[2][3];")

library(unglue)
patterns <- 
  c("{id} {Message} («{Comment}»){}",
    "{} {Message} ({Comment}){}")

unglue_data(txt, patterns)
#>     id   Message       Comment
#> 1    1   message random_choice
#> 2    2     reply          asdf
#> 3    3  regulate random_choice
#> 4    4 Early reg  for instance
#> 5 <NA>   Success     something
#> 6    6        OK          fine