web-dev-qa-db-fra.com

Comment transformer des données XML en un data.frame?

J'essaie d'apprendre le package XML de R. J'essaie de créer un data.frame à partir d'un exemple de fichier de données xml books.xml. Voici ce que j'obtiens:

library(XML)
books <- "http://www.w3schools.com/XQuery/books.xml"
doc <- xmlTreeParse(books, useInternalNodes = TRUE)
doc
xpathApply(doc, "//book", function(x) do.call(paste, as.list(xmlValue(x))))
xpathSApply(doc, "//book", function(x) strsplit(xmlValue(x), " "))
xpathSApply(doc, "//book/child::*", xmlValue)

Chacun de ces xpathSApply ne me rapproche même pas de mon intention. Comment procéder vers un data.frame bien formé?

34
larus

Habituellement, je suggérerais d'essayer la fonction xmlToDataFrame(), mais je pense que ce sera en fait assez délicat car il n'est pas bien structuré au départ.

Je recommanderais de travailler avec cette fonction:

xmlToList(books)

Un problème est qu'il existe plusieurs auteurs par livre, vous devrez donc décider comment gérer cela lorsque vous structurerez votre bloc de données.

Une fois que vous avez décidé quoi faire avec le problème de plusieurs auteurs, il est assez simple de transformer votre liste de livres en un bloc de données avec la fonction ldply() dans plyr (ou utilisez simplement lapply et convertissez la valeur de retour en un data.frame en utilisant do.call ("rbind" ...).

Voici un exemple complet (hors auteur):

library(XML)
books <-  "w3schools.com/xsl/books.xml"
library(plyr)
ldply(xmlToList(books), function(x) { data.frame(x[!names(x)=="author"]) } )

   .id        title.text title..attrs year price   .attrs
 1 book  Everyday Italian           en 2005 30.00  COOKING
 2 book      Harry Potter           en 2005 29.99 CHILDREN
 3 book XQuery Kick Start           en 2003 49.99      WEB
 4 book      Learning XML           en 2003 39.95      WEB

Voici à quoi cela ressemble avec l'auteur inclus. Vous devez utiliser ldply dans ce cas car la liste est "irrégulière" ... lapply ne peut pas gérer cela correctement. [Sinon, vous pouvez utiliser lapply avec rbind.fill (Également gracieuseté de Hadley), mais pourquoi s'embêter quand plyr le fait automatiquement pour vous?]:

ldply(xmlToList(books), data.frame)

   .id        title.text title..attrs              author year price   .attrs
1 book  Everyday Italian           en Giada De Laurentiis 2005 30.00  COOKING
2 book      Harry Potter           en        J K. Rowling 2005 29.99 CHILDREN
3 book XQuery Kick Start           en      James McGovern 2003 49.99      WEB
4 book      Learning XML           en         Erik T. Ray 2003 39.95      WEB
     author.1   author.2   author.3               author.4
1        <NA>       <NA>       <NA>                   <NA>
2        <NA>       <NA>       <NA>                   <NA>
3 Per Bothner Kurt Cagle James Linn Vaidyanathan Nagarajan
4        <NA>       <NA>       <NA>                   <NA>
39
Shane