如何将 Markdown 文件转换为 R DataFrame
How to convert a Markdown file into an R DataFrame
我有以下 markdown
文件 (md3.md),我想使用 XML 转换作为中间步骤将其转换为 R dataframe
。然后可以使用 XML R package
将 XML 文件转换为数据帧。
# level_1
## level_11
- ind1
- ind2
## level_12
- ind3
# level_2
## level_21
### level_211
- ind4
要将 md 文件转换为 XML 我使用了:
library(commonmark)
library(xml2)
md <- readLines("md3.md")
xml <- markdown_xml(md)
write(xml, "md3.xml")
但生成的文件太复杂,我不知道如何将其转换为数据框。
我尝试使用类似于以下内容的 R XML package
,但我不确定如何以正确的方式表达要转换的 XML 文件:
library(XML)
library(dplyr)
xml_doc <- readLines("md3.xml")
myXML <- xmlParse(xml_doc)
myData <- xmlToDataFrame(myXML, stringsAsFactors = FALSE,) %>%
mutate_all(~type.convert(., as.is = T))
此数据框可能需要的输出如下(我使用树级别 L_1, L_2, L_3, indicators
作为使用关系数据库的字段):
L_1 <- c('level_1', 'level_1', 'level_1', 'level_2')
L_2 <- c('level_11', 'level_11', 'level_12', 'level_21')
L_3 <- c('', '', '', 'level_211')
indicators <- c('ind1', 'ind2', 'ind3', 'ind4')
df <- data.frame(L_1, L_2, L_3, indicators)
df
#> L_1 L_2 L_3 indicators
#> 1 level_1 level_11 ind1
#> 2 level_1 level_11 ind2
#> 3 level_1 level_12 ind3
#> 4 level_2 level_21 level_211 ind4
不清楚您究竟希望如何使用具有多个嵌套级别和不同长度元素的结构表示为矩形数据框。我想一种方法是在一行中包含每个元素的类型和内容,如下所示:
library(xml2)
xml_doc <- readLines("md3.xml")
myXML <- xml2::read_xml(xml_doc)
elements <- unlist(xml2::as_list(myXML)$`document`);
data.frame(type = names(elements), contents = as.character(elements))
#> type contents
#> 1 heading.text level_1
#> 2 heading.text level_11
#> 3 list.item.paragraph.text ind1
#> 4 list.item.paragraph.text ind2
#> 5 heading.text level_12
#> 6 list.item.paragraph.text ind3
#> 7 heading.text level_2
#> 8 heading.text level_21
#> 9 heading.text level_211
#> 10 list.item.paragraph.text ind4
有多种方法可以尝试保留嵌套结构,但除非您有特定的目标,否则它们都有些武断和人为。如果您想扩展您的问题,我很乐意帮助您实现这一目标。
编辑
有了 OP 现在指定的所需输出,就可以提取我们维护嵌套结构所需的数据。首先,我们需要提取 "level" 属性以及 xml 中的任何内容。我们可以用递归函数来做到这一点:
list_miner <- function(x)
{
if(!is.null(attr(x, "level"))) return(c(level = attr(x, "level"), x[[1]]))
if(class(x) == "list") return(lapply(x, list_miner))
else return(c( x))
}
我们这样应用函数:
xml_doc <- readLines("md3.xml")
myXML <- xml2::read_xml(xml_doc)
xlist <- xml2::as_list(myXML)
elements <- unlist(lapply(xlist, list_miner))
df <- data.frame(type = names(elements), contents = as.character(elements))
现在df
包含了我们需要的所有信息:
#> type contents
#> 1 document.heading.level 1
#> 2 document.heading level_1
#> 3 document.heading.level 2
#> 4 document.heading level_11
#> 5 document.list.item.paragraph.text ind1
#> 6 document.list.item.paragraph.text ind2
#> 7 document.heading.level 2
#> 8 document.heading level_12
#> 9 document.list.item.paragraph.text ind3
#> 10 document.heading.level 1
#> 11 document.heading level_2
#> 12 document.heading.level 2
#> 13 document.heading level_21
#> 14 document.heading.level 3
#> 15 document.heading level_211
#> 16 document.list.item.paragraph.text ind4
将其转换为正确的格式需要进行大量修改,但实现方法如下:
df %>%
mutate(level1 = cumsum(1 * (type == "document.heading.level" & contents == "1"))) %>%
group_by(level1) %>%
mutate(level1text = contents[type == "document.heading"][1]) %>%
filter(level1 == 0 | seq_along(type) > 2) %>%
mutate(level2 = cumsum(1 * (type == "document.heading.level" & contents == "2"))) %>%
group_by(level1, level2) %>%
mutate(level2text = contents[type == "document.heading"][1]) %>%
filter(level2 == 0 | seq_along(type) > 2) %>%
mutate(level3 = cumsum(1 * (type == "document.heading.level" & contents == "3"))) %>%
group_by(level1, level2, level3) %>%
mutate(level3text = contents[type == "document.heading"][1]) %>%
filter(level3 == 0 | seq_along(type) > 2) %>%
ungroup() %>%
select(header_level_1 = level1text, header_level_2 = level2text,
header_level_3 = level3text, text = contents)
产生:
#> # A tibble: 4 x 4
#> header_level_1 header_level_2 header_level_3 text
#> <fct> <fct> <fct> <fct>
#> 1 level_1 level_11 <NA> ind1
#> 2 level_1 level_11 <NA> ind2
#> 3 level_1 level_12 <NA> ind3
#> 4 level_2 level_21 level_211 ind4
我有以下 markdown
文件 (md3.md),我想使用 XML 转换作为中间步骤将其转换为 R dataframe
。然后可以使用 XML R package
将 XML 文件转换为数据帧。
# level_1
## level_11
- ind1
- ind2
## level_12
- ind3
# level_2
## level_21
### level_211
- ind4
要将 md 文件转换为 XML 我使用了:
library(commonmark)
library(xml2)
md <- readLines("md3.md")
xml <- markdown_xml(md)
write(xml, "md3.xml")
但生成的文件太复杂,我不知道如何将其转换为数据框。
我尝试使用类似于以下内容的 R XML package
,但我不确定如何以正确的方式表达要转换的 XML 文件:
library(XML)
library(dplyr)
xml_doc <- readLines("md3.xml")
myXML <- xmlParse(xml_doc)
myData <- xmlToDataFrame(myXML, stringsAsFactors = FALSE,) %>%
mutate_all(~type.convert(., as.is = T))
此数据框可能需要的输出如下(我使用树级别 L_1, L_2, L_3, indicators
作为使用关系数据库的字段):
L_1 <- c('level_1', 'level_1', 'level_1', 'level_2')
L_2 <- c('level_11', 'level_11', 'level_12', 'level_21')
L_3 <- c('', '', '', 'level_211')
indicators <- c('ind1', 'ind2', 'ind3', 'ind4')
df <- data.frame(L_1, L_2, L_3, indicators)
df
#> L_1 L_2 L_3 indicators
#> 1 level_1 level_11 ind1
#> 2 level_1 level_11 ind2
#> 3 level_1 level_12 ind3
#> 4 level_2 level_21 level_211 ind4
不清楚您究竟希望如何使用具有多个嵌套级别和不同长度元素的结构表示为矩形数据框。我想一种方法是在一行中包含每个元素的类型和内容,如下所示:
library(xml2)
xml_doc <- readLines("md3.xml")
myXML <- xml2::read_xml(xml_doc)
elements <- unlist(xml2::as_list(myXML)$`document`);
data.frame(type = names(elements), contents = as.character(elements))
#> type contents
#> 1 heading.text level_1
#> 2 heading.text level_11
#> 3 list.item.paragraph.text ind1
#> 4 list.item.paragraph.text ind2
#> 5 heading.text level_12
#> 6 list.item.paragraph.text ind3
#> 7 heading.text level_2
#> 8 heading.text level_21
#> 9 heading.text level_211
#> 10 list.item.paragraph.text ind4
有多种方法可以尝试保留嵌套结构,但除非您有特定的目标,否则它们都有些武断和人为。如果您想扩展您的问题,我很乐意帮助您实现这一目标。
编辑
有了 OP 现在指定的所需输出,就可以提取我们维护嵌套结构所需的数据。首先,我们需要提取 "level" 属性以及 xml 中的任何内容。我们可以用递归函数来做到这一点:
list_miner <- function(x)
{
if(!is.null(attr(x, "level"))) return(c(level = attr(x, "level"), x[[1]]))
if(class(x) == "list") return(lapply(x, list_miner))
else return(c( x))
}
我们这样应用函数:
xml_doc <- readLines("md3.xml")
myXML <- xml2::read_xml(xml_doc)
xlist <- xml2::as_list(myXML)
elements <- unlist(lapply(xlist, list_miner))
df <- data.frame(type = names(elements), contents = as.character(elements))
现在df
包含了我们需要的所有信息:
#> type contents
#> 1 document.heading.level 1
#> 2 document.heading level_1
#> 3 document.heading.level 2
#> 4 document.heading level_11
#> 5 document.list.item.paragraph.text ind1
#> 6 document.list.item.paragraph.text ind2
#> 7 document.heading.level 2
#> 8 document.heading level_12
#> 9 document.list.item.paragraph.text ind3
#> 10 document.heading.level 1
#> 11 document.heading level_2
#> 12 document.heading.level 2
#> 13 document.heading level_21
#> 14 document.heading.level 3
#> 15 document.heading level_211
#> 16 document.list.item.paragraph.text ind4
将其转换为正确的格式需要进行大量修改,但实现方法如下:
df %>%
mutate(level1 = cumsum(1 * (type == "document.heading.level" & contents == "1"))) %>%
group_by(level1) %>%
mutate(level1text = contents[type == "document.heading"][1]) %>%
filter(level1 == 0 | seq_along(type) > 2) %>%
mutate(level2 = cumsum(1 * (type == "document.heading.level" & contents == "2"))) %>%
group_by(level1, level2) %>%
mutate(level2text = contents[type == "document.heading"][1]) %>%
filter(level2 == 0 | seq_along(type) > 2) %>%
mutate(level3 = cumsum(1 * (type == "document.heading.level" & contents == "3"))) %>%
group_by(level1, level2, level3) %>%
mutate(level3text = contents[type == "document.heading"][1]) %>%
filter(level3 == 0 | seq_along(type) > 2) %>%
ungroup() %>%
select(header_level_1 = level1text, header_level_2 = level2text,
header_level_3 = level3text, text = contents)
产生:
#> # A tibble: 4 x 4
#> header_level_1 header_level_2 header_level_3 text
#> <fct> <fct> <fct> <fct>
#> 1 level_1 level_11 <NA> ind1
#> 2 level_1 level_11 <NA> ind2
#> 3 level_1 level_12 <NA> ind3
#> 4 level_2 level_21 level_211 ind4