我有一个以下格式的文本文件
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语句,而且还要保持前一行似乎很快就会变得很复杂,因此寻求帮助!
答案 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创建