收集列表中的所有缩进行

时间:2018-10-18 14:06:36

标签: r text stringr

我有一个以下格式的文本文件

Information I want:
    info1 a
    info2 b
    info3 c
More information I want:
    info1 1 
    info2 2
    info3 3

我想在R中解析此文件,以便所有缩进的行都在列表中的相同命名向量内。

即。这样结果如下所示:

list(infoIwant = list(info1 = "a", info2 = "b", info3 = "c"),
 otherinfo = list(info1 = "1", info2 = "2", info3 = "3"))

有人对此有任何建议吗?我能想到的唯一方法是涉及一系列依赖于该行开头的if语句,而且还要保持前一行似乎很快就会变得很复杂,因此寻求帮助!

1 个答案:

答案 0 :(得分:1)

我将使用几个tidyverse函数来做到这一点。将数据放在纯文本文件中可能更有意义-我只需要使用它作为字符串与reprex配合使用即可。

基本readLines需要文件或其他连接,但是readr::read_lines允许您读取字符串。同样,在实践中也许无关紧要。读入此内容可以获取一个矢量,文件中每行一个条目。

library(tidyverse)

text <- "Information I want:
    info1 a
    info2 b
    info3 c
More information I want:
    info1 1 
    info2 2
    info3 3
"

read_lines(text)
#> [1] "Information I want:"      "    info1 a"             
#> [3] "    info2 b"              "    info3 c"             
#> [5] "More information I want:" "    info1 1 "            
#> [7] "    info2 2"              "    info3 3"

将其转换为数据帧-我使用了as_tibble,然后给了我该向量的列value。然后,我将其分为两列,并用正则表达式\\s{2,}进行拆分,即在两个或多个连续空格处进行拆分。这样会将空白区域变成第一列中自己的条目。

read_lines(text) %>%
  as_tibble() %>%
  separate(value, into = c("header", "info"), sep = "\\s{2,}")
#> # A tibble: 8 x 2
#>   header                   info      
#>   <chr>                    <chr>     
#> 1 Information I want:      <NA>      
#> 2 ""                       info1 a   
#> 3 ""                       info2 b   
#> 4 ""                       info3 c   
#> 5 More information I want: <NA>      
#> 6 ""                       "info1 1 "
#> 7 ""                       info2 2   
#> 8 ""                       info3 3

但是这些空白对于使用并不是那么有用。将空格转换为NA,因此您可以使用tidyr::fill在标头列中的任何NA之前加上任何非NA值。进行过滤以删除“信息”列中的NA(那些仅具有标题但没有信息的地方),并修剪info中剩余的空白区域。

read_lines(text) %>%
  as_tibble() %>%
  separate(value, into = c("header", "info"), sep = "\\s{2,}") %>%
  mutate(header = na_if(header, "")) %>%
  fill(header) %>%
  filter(!is.na(info)) %>%
  mutate(info = str_trim(info))
#> # A tibble: 6 x 2
#>   header                   info   
#>   <chr>                    <chr>  
#> 1 Information I want:      info1 a
#> 2 Information I want:      info2 b
#> 3 Information I want:      info3 c
#> 4 More information I want: info1 1
#> 5 More information I want: info2 2
#> 6 More information I want: info3 3

最后,要从此数据框中获取命名列表,可以将数据框除以header。这为您提供了两个数据帧的列表。如果您在该列表上映射并调用dplyr::pull,则可以仅将info列作为每个列表条目的向量。

read_lines(text) %>%
  as_tibble() %>%
  separate(value, into = c("header", "info"), sep = "\\s{2,}") %>%
  mutate(header = na_if(header, "")) %>%
  fill(header) %>%
  filter(!is.na(info)) %>%
  mutate(info = str_trim(info)) %>%
  split(.$header) %>%
  map(pull, info)
#> $`Information I want:`
#> [1] "info1 a" "info2 b" "info3 c"
#> 
#> $`More information I want:`
#> [1] "info1 1" "info2 2" "info3 3"

reprex package(v0.2.1)于2018-10-18创建