【问题标题】:Storing data from a for loop in a data frame将来自 for 循环的数据存储在数据框中
【发布时间】:2016-12-02 18:51:44
【问题描述】:

我正在尝试创建一个与 pubmed api 交互的函数,以检索与 100 个出版物关联的 xml 文件。然后我想单独解析 xml 文件以检索每个出版物的标题和每个出版物的摘要。我正在使用 Rentrez 包与 api 交互,并已成功检索到必要的 xml 文件。我正在使用 xml 包来解析 xml 文件,并已验证 Xpath 表达式是否检索到我想要的数据。事实上,我希望从其他领域(期刊标题、网格术语等)获取数据,但我被困在这一步)

但是,我无法创建适当的 for 循环来将此数据移动到数据框中。我在运行代码时收到以下错误:

$<-.data.frame(*tmp*, "Abstract", value = list("text of abstract") 中的错误: 替换有 1 行,数据有 0

当我测试接收标题信息的函数(通过删除表达式以检索抽象信息)时,我收到一个空的数据框,其中没有关于我想要的标题的信息。但是没有错误信息。

如果我执行 pubmed_pa​​rsed("Kandel+Eric", n=2),我的目标是接收一个数据帧,其中包含来自“ATitle”列中两个标题的字符向量(标题:“Roles for small noncoding RNAs in哺乳动物大脑中反转录转座子的沉默”和“ApCPEB4,一种含有 ApCPEB 同源物的非朊病毒结构域,参与了长期促进的启动”)。并且两个摘要中的字符向量相应地出现在“摘要”列中(摘要的部分:“Piwi-interacting RNAs (piRNAs), longthought to be limited to 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
}

【问题讨论】:

  • 请包括库声明和其他任何使此可重现所需的内容
  • 我已经添加了适当的库语句,以及我希望从正确构造的“pubmed_pa​​rsed”函数中接收到的示例。谢谢。
  • 注意:library(XML) 全部大写。 R 区分大小写!
  • 如果我们无法访问 API,请查看示例 XML 会有所帮助。为什么 xpath 表达式会重复?
  • pubmed api 对每个人都是免费的。我有重复的路径表达式以从同一出版物中检索各种信息。因此,xpath 表达式旨在检索摘要和标题信息。如果我在一个查询中检索多篇文章的书目信息,我会收到一个较大的 xml 文件,这对我来说更难正确解析。这是我首先尝试做的,但没有成功。我无法分离 xml 节点,然后分别在它们上运行路径表达式。

标签: r xml function for-loop pubmed


【解决方案1】:

这是获取表格的一种方法和一些建议。首先,我会使用网络历史记录选项并一起下载所有结果,而不是循环下载。

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>
    ...

如果标签丢失,我通常会创建一个函数来添加 NA,并使用逗号连接多个标签。

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"))

我不确定 MeSH 术语发生了什么,但我只在我下载的几个示例中看到了关键字。此外,可能有几种方法可以获得第一作者和最后作者。您可以同时获取姓氏和首字母(假设两者始终存在)并替换首字母前的逗号以获得​​作者字符串。然后将其拆分以获得第一作者和最后作者,甚至打印下面的前三个。

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" 

【讨论】:

  • 谢谢你!根据您的建议,很容易检索网格术语:MeshTerms = sapply(NodeSet, xpath2, ".//MeshHeading/DescriptorName|.//MeshHeading/QualifierName", xmlGetAttr, "UI")
  • 在得到描述符和限定符的向量后,我通常会运行第二个查询来获取xmlName,然后在限定符之前粘贴一个“\”,最后使用这个answer连接名称和限定符
猜你喜欢
  • 2017-09-08
  • 2021-07-28
  • 2019-04-18
  • 1970-01-01
  • 2016-11-25
  • 1970-01-01
  • 2017-06-11
  • 2019-10-22
  • 1970-01-01
相关资源
最近更新 更多