我正在尝试创建一个与PubMed API交互的函数,以检索与100个出版物关联的XML文件。然后,我想单独解析XML文件以检索每个出版物的标题和每个出版物的摘要。我正在使用Rentrez软件包与API进行交互,并成功检索了必要的XML文件。我正在使用XML软件包来解析XML文件,并已验证XPath表达式是否检索了我想要的数据。实际上,我希望从其他字段(期刊标题,网格术语等)获取数据
但是,我无法为循环创建适当的循环将这些数据移动到数据框架中。我从运行代码中收到以下错误:
$<-.data.frame
中的错误( *tmp*
,"摘要",value = list("摘要"文本):替换有1行,数据具有0
当我测试该功能以接收标题信息(通过删除表达式以检索抽象信息)时,我收到一个空的数据框架,而没有有关我想要的标题的信息。但是没有错误消息。
如果我执行PubMed_parsed(" Kandel Eric",n = 2),我的目标是从" Atitle"列中的两个标题中接收一个具有字符矢量的数据框架(标题:在哺乳动物大脑中的逆转座子沉默"one_answers"含有APCPEB同源物的非pro域APCPEB4参与了长期促进的启动")。从两个摘要到相应地出现在"摘要"(摘要的一部分:" Piwi-Interactering RNA(PIRNA))中的角色向量,长期以来一直认为是Gremlin ..."蛋白质合成是突触特异性的……")。
library(xml)
library(rentrez)
pubmed_parsed <- function(term, n=100){
df <- data.frame(ATitle = character(), JTitle = character(), MeshTerms = character(), Abstract = character(), FAuthor = character(), LAuthor = character(), stringsAsFactors = FALSE)
IdList <- entrez_search(db = "pubmed", term = term, retmode = "xml", retmax = n)
for (i in 1:n){
XmlFile <- entrez_fetch(db = "pubmed", id=IdList$ids[i], rettype = "xml", retmode = "xml", parsed=TRUE)
Parsed <- xmlRoot(XmlFile)
df$ATitle[i] <- xpathSApply(Parsed, "/PubmedArticleSet/PubmedArticle/MedlineCitation/Article/Title", xmlValue, simplify = FALSE)
df$Abstract[i] <- xpathSApply(Parsed, "/PubmedArticleSet/PubmedArticle/MedlineCitation/Article/Title", xmlValue, simplify = FALSE)
}
df
}
这是获取表和一些建议的一种方法。首先,我将使用Web历史记录选项并将所有结果下载在一起,而不是通过下载循环。
ids <- entrez_search(db = "pubmed", term = "Kandel ER", use_history = TRUE)
ids
Entrez search result with 502 hits (object contains 20 IDs and a web_history object)
Search term (as translated): Kandel ER[Author]
doc <- entrez_fetch(db="pubmed", web_history=ids$web_history, rettype="xml", retmax = 3, parsed=TRUE)
接下来,将文章放入节点集中并查询以处理所有缺失和多个标签。
articles <- getNodeSet( doc, "//PubmedArticle")
length(articles)
[1] 3
articles[[1]]
<PubmedArticle>
<MedlineCitation Status="Publisher" Owner="NLM">
<PMID Version="1">27791114</PMID>
<DateCreated>
...
我通常会创建一个函数以添加NAS,如果标签丢失,并使用逗号连接多个标签。
xpath2 <-function(x, path, fun = xmlValue, ...){
y <- xpathSApply(x, path, fun, ...)
ifelse(length(y) == 0, NA,
ifelse(length(y) > 1, paste(unlist(y), collapse=", "), y))
}
然后只需将该函数应用于节点(XPath中的领先点,因此相对于该节点)。这将将多个关键字合并到逗号分隔的列表中,并在第3条中包含缺少关键字的NA。
sapply(articles, xpath2, ".//Keyword")
[1] "DNA methylation, behavior, endogenous siRNA, piwi-interacting RNA, transposon"
[2] "Aplysia, CPEB, CPEB4, Long-term facilitation"
[3] NA
大多数XPath应该工作
sapply(articles, xpath2, ".//PubDate/Year")
[1] "2016" "2016" "2016"
sapply(articles, xpath2, ".//ArticleId[@IdType='pmc']")
[1] "PMC5111663" "PMC5075418" NA
如果需要,也可以使用xmlGetAttr
sapply(articles, xpath2, ".//Article", xmlGetAttr, "PubModel")
[1] "Print-Electronic" "Electronic" "Electronic"
最后,创建一个data.frame
data.frame(
ATitle = sapply(articles, xpath2, ".//ArticleTitle"),
JTitle = sapply(articles, xpath2, ".//Journal/Title"),
Keywords = sapply(articles, xpath2, ".//Keyword"),
Authors = sapply(articles, xpath2, ".//Author/LastName"),
Abstract = sapply(articles, xpath2, ".//AbstractText"))
我不确定网格术语发生了什么,但是我只在下载的几个示例中看到了关键字。另外,可能有几种方法可以获得第一和最后的作者。您可以同时获得姓氏和缩写(假设两者总是存在),然后在缩写之前替换逗号以获取作者字符串。然后将其拆分以获得第一位和最后一个作者,甚至在下面打印出前三个。
au <- sapply(articles, xpath2, ".//Author/LastName|.//Author/Initials")
au <- gsub(",( [A-Z]+,?)", "\1", au)
authors_etal <- function(x, authors=3, split=", *"){
y <- strsplit(x, split)
sapply(y, function(x){
if(length(x) > (authors + 1)) x <- c(x[1:authors], "et al.")
paste(x, collapse=", ")
})
}
authors_etal(au)
[1] "Nandi S, Chandramohan D, Fioriti L, et al."
[2] "Lee SH, Shim J, Cheong YH, et al."
[3] "Si K, Kandel ER"