[英]convert cellosaurus.xml file into a data.frame in R
我有一個XML文件,但我無法將其轉換成良好的data.frame格式。 我已經接近了,但還沒到那兒。
cellosaurus.xml通過刪除<cell-line-list>
和</cell-line-list>
標記之前和之后的所有內容對該文件進行了少許修改。
到目前為止,這是我編寫的凌亂代碼:
require(XML)
require(xml2)
require(rvest)
require(dplyr)
require(xmltools)
require(stringi)
require(gtools)
setwd("~/Documents/Cancer_Cell_Lines/Cellosaurus")
file <- "cellosaurus.xml"
cellosaurus <- file %>% xml2::read_xml()
nodeset <- cellosaurus %>% xml_children()
terminal_xpaths <- nodeset[1] %>% xml_get_paths() %>% unlist() %>% unique()
terminal_nodesets <- lapply(terminal_xpaths[1], xml2::xml_find_all, x = cellosaurus)
df_list <- terminal_nodesets %>% purrr::map(xml_dig_df)
df <- lapply(df_list[[1]], function(x) as.data.frame(x))
table <- do.call("smartbind", df)
問題1:有重復的列名混在一起。 例如,在文件中,有許多路徑最終到達名為cv.term的節點,例如
"/cell-line-list/cell-line/disease-list/cv-term"
"/cell-line-list/cell-line/species-list/cv-term"
"/cell-line-list/cell-line/derived-from/cv-term"
但是在表中,我得到了名為cv.term
, cv.term.1
, cv.term.2
列,但是由於缺少數據, cv.term.2
內容混淆。 有沒有辦法解決這個問題。
問題2:文件很大,需要很長時間才能運行(我只能在完整文件的一小部分上進行測試),但我無法弄清楚如何正確分割xml,除了通過分割成盡可能多的文件,大約有109,000個節點。 然后,我很難將這么多文件合並到我的代碼中以供R讀取。
任何幫助表示贊賞。
要使用關系數據庫術語,請考慮數據規范化。 具體來說,請保持數據的長度,因為XML中的大多數節點實際上都是一對多列表,您可以將每個列表提取為單獨的長數據幀,並通過諸如cell_line節點號之類的唯一ID合並在一起。
幸運的是,有一個功能強大的提取工具稱為XSLT ,這是一種專用的聲明性語言(與SQL相同的類型),旨在將XML轉換為各種最終用途需求,例如提取可以更簡單地解析為數據幀的各個片段,以及然后將所有項目合並在一起。 XSLT也與R無關,它可以移植到其他應用程序層(Java,PHP,Python)或專用XSLT處理器中,這也是其優點 。
有關最終解決方案的路線圖,請參見下面的過程。 下面的所有XSLT腳本都從每個單元行節點的特定部分進行解析,並將XML展平為一個子級別:
library(xml2)
library(xslt) # INSTALL PACKAGE BEFORE HAND
library(dplyr) # ONLY FOR bind_rows
# PARSE XML AND XSLT
doc <- read_xml('Cellosaurus.xml')
scripts <- list.files(path='/path/to/xslt/scripts', pattern='.xsl')
xpaths <- c('//accession', '//cell-line', '//hla_gene', '//marker',
'//name', '//species_list', '//url')
proc_xml_parse <- function(x, s) {
style <- read_xml(s, package = "xslt")
# TRANSFORM INPUT INTO OUTPUT
new_xml <- xslt::xml_xslt(doc, style)
# INNER DF LIST BUILD
df_list <- lapply(xml_find_all(new_xml, x), function(x) {
vals <- xml_children(x)
setNames(data.frame(t(xml_text(vals)), stringsAsFactors = FALSE), xml_name(vals))
})
bind_rows(df_list)
}
# OUTER DF LIST BUILD
df_list <- Map(proc_xml_parse, xpaths, scripts)
# CHAIN MERGE
final_df <- Reduce(function(x,y) merge(x, y, by="cell_num", all=TRUE), df_list)
將每個文件另存為單獨的.xsl或.xslt文件(特殊.xml文件),以將其加載到上述R中。 通過復制XML中其他列表節點的模式來添加更多XSLT腳本,如下所示,它不能捕獲全部。
細胞系列表
<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
<xsl:output method="xml" version="1.0" encoding="UTF-8" indent="yes"/>
<xsl:strip-space elements="*"/>
<xsl:template match="Cellosaurus">
<xsl:copy>
<xsl:apply-templates select="cell-line-list/cell-line"/>
</xsl:copy>
</xsl:template>
<xsl:template match="cell-line">
<xsl:copy>
<cell_num>
<xsl:value-of select="count(preceding-sibling::*)+1"/>
</cell_num>
<xsl:for-each select="@*">
<xsl:element name="{name(.)}">
<xsl:value-of select="."/>
</xsl:element>
</xsl:for-each>
</xsl:copy>
</xsl:template>
</xsl:stylesheet>
加入清單
<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
<xsl:output method="xml" version="1.0" encoding="UTF-8" indent="yes"/>
<xsl:strip-space elements="*"/>
<xsl:template match="Cellosaurus">
<xsl:copy>
<xsl:apply-templates select="cell-line-list/cell-line"/>
</xsl:copy>
</xsl:template>
<xsl:template match="cell-line">
<xsl:apply-templates select="accession-list"/>
</xsl:template>
<xsl:template match="accession-list">
<xsl:apply-templates select="accession"/>
</xsl:template>
<xsl:template match="accession">
<xsl:copy>
<cell_num>
<xsl:value-of select="count(ancestor::cell-line[1]/preceding-sibling::*)+1"/>
</cell_num>
<xsl:for-each select="@*">
<xsl:element name="{name(.)}">
<xsl:value-of select="."/>
</xsl:element>
</xsl:for-each>
<accession_value><xsl:value-of select="."/></accession_value>
</xsl:copy>
</xsl:template>
</xsl:stylesheet>
名單
<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
<xsl:output method="xml" version="1.0" encoding="UTF-8" indent="yes"/>
<xsl:strip-space elements="*"/>
<xsl:template match="Cellosaurus">
<xsl:copy>
<xsl:apply-templates select="cell-line-list/cell-line"/>
</xsl:copy>
</xsl:template>
<xsl:template match="cell-line">
<xsl:apply-templates select="name-list"/>
</xsl:template>
<xsl:template match="name-list">
<xsl:apply-templates select="name"/>
</xsl:template>
<xsl:template match="name">
<xsl:copy>
<cell_num>
<xsl:value-of select="count(ancestor::cell-line/preceding-sibling::*)+1"/>
</cell_num>
<xsl:for-each select="@*">
<xsl:element name="{name(.)}">
<xsl:value-of select="."/>
</xsl:element>
</xsl:for-each>
<name_value><xsl:value-of select="."/></name_value>
</xsl:copy>
</xsl:template>
</xsl:stylesheet>
網頁列表
<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
<xsl:output method="xml" version="1.0" encoding="UTF-8" indent="yes"/>
<xsl:strip-space elements="*"/>
<xsl:template match="Cellosaurus">
<xsl:copy>
<xsl:apply-templates select="cell-line-list/cell-line"/>
</xsl:copy>
</xsl:template>
<xsl:template match="cell-line">
<xsl:apply-templates select="web-page-list"/>
</xsl:template>
<xsl:template match="web-page-list">
<xsl:apply-templates select="url"/>
</xsl:template>
<xsl:template match="url">
<xsl:copy>
<cell_num>
<xsl:value-of select="count(ancestor::cell-line/preceding-sibling::*)+1"/>
</cell_num>
<xsl:for-each select="@*">
<xsl:element name="{name(.)}">
<xsl:value-of select="."/>
</xsl:element>
</xsl:for-each>
<url_value><xsl:value-of select="."/></url_value>
</xsl:copy>
</xsl:template>
</xsl:stylesheet>
HLA列表
<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
<xsl:output method="xml" version="1.0" encoding="UTF-8" indent="yes"/>
<xsl:strip-space elements="*"/>
<xsl:template match="Cellosaurus">
<xsl:copy>
<xsl:apply-templates select="cell-line-list/cell-line"/>
</xsl:copy>
</xsl:template>
<xsl:template match="cell-line">
<xsl:apply-templates select="hla-lists/hla-list"/>
</xsl:template>
<xsl:template match="hla-list">
<xsl:apply-templates select="hla-gene"/>
</xsl:template>
<xsl:template match="hla-gene">
<hla_gene>
<cell_num>
<xsl:value-of select="count(ancestor::cell-line/preceding-sibling::*)+1"/>
</cell_num>
<xsl:for-each select="@*">
<xsl:element name="{name(.)}">
<xsl:value-of select="."/>
</xsl:element>
</xsl:for-each>
<hla_value><xsl:value-of select="."/></hla_value>
</hla_gene>
</xsl:template>
</xsl:stylesheet>
特別清單
<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
<xsl:output method="xml" version="1.0" encoding="UTF-8" indent="yes"/>
<xsl:strip-space elements="*"/>
<xsl:template match="Cellosaurus">
<xsl:copy>
<xsl:apply-templates select="cell-line-list/cell-line"/>
</xsl:copy>
</xsl:template>
<xsl:template match="cell-line">
<xsl:apply-templates select="species-list/cv-term"/>
</xsl:template>
<xsl:template match="cv-term">
<species_list>
<cell_num>
<xsl:value-of select="count(ancestor::cell-line/preceding-sibling::*)+1"/>
</cell_num>
<xsl:for-each select="@*">
<xsl:element name="{name(.)}">
<xsl:value-of select="."/>
</xsl:element>
</xsl:for-each>
<species_value><xsl:value-of select="."/></species_value>
</species_list>
</xsl:template>
</xsl:stylesheet>
標記清單
<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
<xsl:output method="xml" version="1.0" encoding="UTF-8" indent="yes"/>
<xsl:strip-space elements="*"/>
<xsl:template match="Cellosaurus">
<xsl:copy>
<xsl:apply-templates select="cell-line-list/cell-line"/>
</xsl:copy>
</xsl:template>
<xsl:template match="cell-line">
<xsl:apply-templates select="str-list"/>
</xsl:template>
<xsl:template match="str-list">
<xsl:apply-templates select="marker-list"/>
</xsl:template>
<xsl:template match="marker-list">
<xsl:apply-templates select="marker"/>
</xsl:template>
<xsl:template match="marker">
<xsl:copy>
<cell_num>
<xsl:value-of select="count(ancestor::cell-line/preceding-sibling::*)+1"/>
</cell_num>
<xsl:for-each select="@*">
<xsl:element name="{name(.)}">
<xsl:value-of select="."/>
</xsl:element>
</xsl:for-each>
<xsl:copy-of select="marker-data-list/marker-data/alleles"/>
</xsl:copy>
</xsl:template>
</xsl:stylesheet>
鏈合並后,對於長數據幀(多對多),類似於SQL連接的每個唯一行的值重復。 請注意:如果不想在合並的輸出下面有一個數據幀的命名列表:
只需發表一則評論:當您說“〜109,000個細胞系,每個細胞系之間缺失數據的變化”時,您需要了解Cellosaurus條目中唯一的必填字段是主要材料,細胞系名稱(標識符),單元格類別和分類,則不需要其余所有內容。 所有這些都在cellosaurus.xsd文件中描述,根據字段類型,使用“ minoccurs =” 0“或使用” optional“。
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.