2016-05-12 1 views
3

ceci est mon premier post ici, donc s'il vous plaît pardonnez les erreurs wrt les directives de publicationlapply sur la liste des objets xml

Je suis en train de lire des données XML à partir de PubMed, pour extraire des données sur les affiliations auteur

chaque entrée contient un ensemble de noeuds comme ceci:

<AuthorList> 
      <Author> 
      <LastName>Serra-Blasco</LastName> 
      <ForeName>Maria</ForeName> 
      <Initials>M</Initials> 
      <AffiliationInfo> 
       <Affiliation>Department of Psychiatry, Hospital de la Santa Creu i Sant Pau, Biomedical Research Institute Sant Pau (IIB Sant Pau), Universitat Autònoma de Barcelona (UAB), Centro de Investigación Biomédica en Red de Salud Mental (CIBERSAM), Barcelona, Catalonia, Spain.</Affiliation> 
      </AffiliationInfo> 
      </Author> 
      ... 

Je voudrais finir avec un dataframe qui contient chaque nom de l'auteur et l'affiliation à une ligne.

J'ai essayé de le faire en utilisant xpathSApply pour analyser les nœuds en lisant "// Author", et je me suis retrouvé avec une liste de nœuds xml.

L'analyse syntaxique s'avère être un problème: j'ai écrit du code qui fonctionne sur un élément individuel de cette liste;

pour, par exemple, si la liste est authorlist

je peux extraire un tableau approprié pour authorlist[[1]] utiliser cette fonction (qui utilise xpathSApply dans l'élément)

Mais lorsque je tente d'envelopper lapply autour de cette fonction, il me donne une erreur qui dit qu'il ne peut pas exécuter xpathApply sur une liste. L'appel d'erreur exacte est:

Erreur dans UseMethod (« xpathApply »): aucune méthode applicable pour « xpathApply » appliquée à un objet de la classe « liste »

Je présume que les appels lapply la liste sous-ensemble avec l'équivalent de [i] alors que ce dont j'ai besoin est [[i]]. Y a-t-il un moyen de contourner ceci? Ou devrais-je réécrire avec d'autres règles à l'esprit?

Je suis ouvert à la réécriture (c'est juste un peu de gaffes autour de ce que je fais) mais ce problème semblait intéressant, j'espère que vous pouvez aider!

Répondre

2

Je préfère utiliser le paquet rvest lorsque je travaille avec des fichiers html/xml. Sur la base de votre exemple simple:

library(rvest) 
myxml<-read_xml("author.xml") 

lastname<-xml_text(xml_nodes(myxml,"LastName")) 
firstname<-xml_text(xml_nodes(myxml,"ForeName")) 
affiliation<-xml_text(xml_nodes(myxml,"Affiliation")) 
df<-data.frame(firstname, lastname, affiliation) 

Si la structure des modifications du fichier xml, puis demandâmes data.frame commande sera erreur et un travail supplémentaire est nécessaire pour analyser correctement le fichier.

+0

Merci beaucoup! va explorer ce paquet, on dirait qu'il va trier mes problèmes immédiats ... mais y a-t-il aussi un moyen de contourner le problème lapply plus général que je semble avoir rencontré? Je ne sais pas si c'est quelque chose qui arriverait à moins que l'on travaille avec cette structure particulière ... –

+1

xml_nodes retournera un vecteur avec tous les nœuds avec cette balise. Vous ne devriez pas avoir besoin d'utiliser lapplication si la structure est cohérente. Voir la documentation associée aux paquets rvest et xml2 pour des exemples. – Dave2e

1

Il serait utile de montrer votre code qui a produit l'erreur, mais vous pouvez essayer xmlToDataFrame

url <- "http://eutils.ncbi.nlm.nih.gov/entrez/eutils/efetch.fcgi?db=pubmed&id=23620451&rettype=XML" 
doc <- xmlParse(url) 

xmlToDataFrame(doc["//Author"]) 
      LastName ForeName Initials     AffiliationInfo 
1  Serra-Blasco Maria  M Department of Psychiatry...Spain. 
2   Portella Maria J  MJ        <NA> 
3  Gómez-Ansón Beatriz  B        <NA> 
... 

Si vous obtenez des noeuds qui ont zéro ou plusieurs balises, je crée habituellement une fonction pour définir les balises manquantes à NA et un délimiteur pour joindre plusieurs étiquettes.

authors <- getNodeSet(doc, "//Author") 

xpath2 <-function(x, path){ 
    y <- xpathSApply(x, path, xmlValue) 
    ifelse(length(y)==0, NA, 
     ifelse(length(y)>1, paste(y, collapse=", "), y)) 
} 

last <- sapply(authors, xpath2, ".//LastName") 
aff <- sapply(authors, xpath2, ".//Affiliation") 
data.frame(last, aff) 
       last        aff 
1  Serra-Blasco Department of Psychiatry...Spain. 
2   Portella        <NA> 
3  Gómez-Ansón        <NA>