2017-05-18 8 views
1

これは長い間巻き込まれているので、私と一緒に裸にしてください。リストの各親ノードのxmlchildrenの数を計算するR

entrez_fetchは一度に特定の番号しか実行できないため、私は2000個のPMIDをいくつかのベクトル(長さがそれぞれ約500)で1つのリストに分解しました。 。私がPubMEDを照会すると、各出版物のXMLファイルから情報を抽出しています。私は終わりにしたいと思いますが、このようなものです:

Original.PMID  Publication.type 
    26956987   Journal.article 
    26956987   Meta.analysis 
    26956987   Multicenter.study 
    26402000   Journal.article 
    25404043   Journal.article 
    25404043   Meta.analysis 

各公報には、ユニークなPMIDを持っていますが、各PMIDに関連するいくつかの出版物の種類(上で見たような)があるかもしれません。私はXMLファイルからPMID番号を問い合わせることができ、各PMIDの公開タイプを取得できます。私が問題を抱えているのは、各PMIDがそれぞれのパブリケーションタイプに関連付けられるようにPMID×回数を繰り返すことです。親のPublicationTypeノードから子ノードの数を取得することによって、複数のサブリストを持つリストに自分のデータがない場合(たとえば、それぞれが独自のデータフレームとして14個のバッチがある場合)、これを行うことができます。しかし、リスト内でこれをどうやって行うのか分かりません。

私のコードは、これまでのところ、このです:

library(rvest) 
library(tidyverse) 
library(stringr) 
library(regexr) 
library(rentrez) 
library(XML) 

pubmed<-my.data.frame 

into.batches<-function(x,n) split(x,cut(seq_along(x),n,labels=FALSE)) 
batches<-into.batches(pubmed.fwd$PMID, 14) 
headings<-lapply(1:14, function(x) {paste0("Batch",x)}) 
names(batches)<-headings 
fwd<-sapply(batches, function(x) entrez_fetch(db="pubmed", id=x, rettype="xml", parsed=TRUE)) 
trial1<-lapply(fwd, function(x) 
    list(pub.type = xpathSApply(x, "//PublicationTypeList/PublicationType", xmlValue), 
    or.pmid = xpathSApply(x, "//ArticleId[@IdType='pubmed']", xmlValue))) 

trial1は私が問題を抱えていますものです。これは、各バッチ内でpub.type用のベクトルとor.pmid用のベクトルを持っているが、それらは異なる長さであるリストを私に提供する。

私は各出版物にいくつの子供の出版物の種類があるか把握しようとしています。そのため、私はPMIDを何回も繰り返すことができます。私は現在、私がやりたいことはありません、次のコードを使用しています:

​​

残念ながら、これはちょうど子供の総数は、各バッチのではなく、各パブリケーション(またはPMID)のためにノードを教えてください。私は迷っている。どんな助けでも大歓迎です、ありがとうございます!

答えて

2

以下はfwdに等しい長さのデータフレームのリストを作成し、記事ノードとxpath関数を適用してpmidとpubtypeを取得する

pmids <- c(11677608, 22328765 ,11337471) 
res <- entrez_fetch(db="pubmed", rettype="xml", id = pmids) 
doc <- xmlParse(res) 
x <- getNodeSet(doc, "//PubmedArticle") 
x1 <- sapply(x, xpathSApply, ".//ArticleId[@IdType='pubmed']", xmlValue) 
x2 <- sapply(x, xpathSApply, ".//PublicationType", xmlValue) 
data.frame(pmid= rep(x1, sapply(x2, length)), pubtype = unlist(x2)) 
     pmid       pubtype 
1 11677608     Journal Article 
2 11677608 Research Support, Non-U.S. Gov't 
3 22328765     Journal Article 
4 22328765 Research Support, Non-U.S. Gov't 
5 11337471     Journal Article 

また、NCBIは200の以上のUIDを使用している場合、HTTPのPOSTメソッドを使用することを言います。 rentrezはPOSTingをサポートしていませんが、数行のコードで実行することができます。

まず、あなたは(微生物ゲノムのテーブルから6171)のPubMed IDの1000年代とベクトルが必要

library(readr) 
x <- read_tsv("ftp://ftp.ncbi.nih.gov/genomes/GENOME_REPORTS/prokaryotes.txt", 
       na = "-", quote = "") 
ids <- unique(x$`Pubmed ID`) 
ids <- ids[ids < 1e9 & !is.na(ids)] 

ポストは、HTTR POSTを使用してNCBIのIDです。

uri = "https://eutils.ncbi.nlm.nih.gov/entrez/eutils/epost.fcgi?" 
response <- httr::POST(uri, body= list(id = paste(ids, collapse=","), db = "pubmed")) 

ウェブの履歴を取得するentrez_postのコード以下の結果を解析します。

doc <- xmlParse(httr::content(response, as="text", encoding="UTF-8")) 
result <- xpathApply(doc, "/ePostResult/*", xmlValue) 
names(result) <- c("QueryKey", "WebEnv") 
class(result) <- c("web_history", "list") 

(あなたが10K以上のものを持っている場合はretstartオプションを使用してまたはループ)最後に、10Kまでのレコードをフェッチ

res <- entrez_fetch(db="pubmed", rettype="xml", web_history=result) 
doc <- xmlParse(res) 

これらは、私のラップトップ上で実行する2番目のを取ります。

articles <- getNodeSet(doc, "//PubmedArticle") 
x1 <- sapply(articles, xpathSApply, ".//ArticleId[@IdType='pubmed']", xmlValue) 
x2 <- sapply(articles, xpathSApply, ".//PublicationType", xmlValue) 

data_frame(pmid= rep(x1, sapply(x2, length)), pubtype = unlist(x2)) 
# A tibble: 9,885 × 2 
     pmid         pubtype 
     <chr>         <chr> 
1 11677608       Journal Article 
2 11677608   Research Support, Non-U.S. Gov't 
3 12950922       Journal Article 
4 12950922   Research Support, Non-U.S. Gov't 
5 22328765       Journal Article 
... 

最後に1つのコメント。記事ごとに1つの行が必要な場合は、通常、複数のタグを区切りリストに結合し、欠落したノードにNAsを追加する関数を作成します。

xpath2 <-function(x, ...){ 
    y <- xpathSApply(x, ...) 
    ifelse(length(y) == 0, NA, paste(y, collapse="; ")) 
} 

data_frame(pmid = sapply(articles, xpath2, ".//ArticleId[@IdType='pubmed']", xmlValue), 
      journal = sapply(articles, xpath2, ".//Journal/Title", xmlValue), 
      pubtypes = sapply(articles, xpath2, ".//PublicationType", xmlValue)) 

# A tibble: 6,172 × 3 
     pmid     journal           pubtypes 
    <chr>     <chr>            <chr> 
1 11677608     Nature Journal Article; Research Support, Non-U.S. Gov't 
2 12950922 Molecular microbiology Journal Article; Research Support, Non-U.S. Gov't 
3 22328765 Journal of bacteriology Journal Article; Research Support, Non-U.S. Gov't 
4 11337471   Genome research         Journal Article 
... 
2

そう情報でarticleIDは、各記事に対して一意であり、ので文献タイプを反復代わりに別個のベクターのデータフレームを作成することを検討し、物品ごとに複数であってもよいです。

次いで、XMLドキュメントの各PubmedArticleノードを横切る具体的には、使用ノードのインデックス付け、[#]、このIDとタイプの共有祖先であるので、必要な子孫へのXPath。すべてのバッチ間で、最終的なマスターデータフレームの場合

trial1 <- lapply(fwd, function(doc) { 
    # RETRIEVE NUMBER OF ARTICLES PER EACH XML 
    num_of_articles <- length(xpathSApply(doc, "//PubmedArticle")) 

    # LOOP THROUGH EACH ARTICLE AND BIND XML VALUES TO DATAFRAME 
    dfList <- lapply(seq(num_of_articles), function(i) 
    data.frame(
    Original.PMID = xpathSApply(doc, paste0("//PubmedArticle[",i,"]/descendant::ArticleId[@IdType='pubmed']"), xmlValue), 
    Publication.type = xpathSApply(doc, paste0("//PubmedArticle[",i,"]/descendant::PublicationTypeList/PublicationType"), xmlValue) 
)) 

    # ROW BIND ALL DFS INTO ONE 
    df <- do.call(rbind, dfList) 
}) 

、ループから再びdo.call(rbind, ...)を実行します:私は別々にXMLの結果を分割するでしょう

finaldf <- do.call(rbind, trial1) 
関連する問題