2016-11-01 3 views
0

В качестве примера, я следующий код XMLПолучение всех дочерних узлов файла XML в data.frame или data.table

tt = '<Nummeraanduiding> 
    <identificatie>0010200000114849</identificatie> 
<aanduidingRecordInactief>N</aanduidingRecordInactief> 
<aanduidingRecordCorrectie>0</aanduidingRecordCorrectie> 
<huisnummer>13</huisnummer> 
<officieel>N</officieel> 
<postcode>9904PC</postcode> 
<tijdvakgeldigheid> 
<begindatumTijdvakGeldigheid>2010051100000000</begindatumTijdvakGeldigheid> 
</tijdvakgeldigheid> 
<inOnderzoek>N</inOnderzoek> 
<typeAdresseerbaarObject>Verblijfsobject</typeAdresseerbaarObject> 
<bron> 
<documentdatum>20100511</documentdatum> 
<documentnummer>2010/NR002F</documentnummer> 
</bron> 
<nummeraanduidingStatus>Naamgeving uitgegeven</nummeraanduidingStatus> 
<gerelateerdeOpenbareRuimte> 
<identificatie>0010300000000444</identificatie> 
</gerelateerdeOpenbareRuimte> 
</Nummeraanduiding> ' 

Цель состоит в том, чтобы преобразовать этот узел (Nummeraanduiding) к data.table (или data.frame также отлично). Одна из проблем заключается в том, что у меня есть много этих Nummeraanduiding узлов (миллионы из них).

Следующий код способен обрабатывать данные:

library(XML) 
# This parses the doc... 
doc = xmlParse(tt) 
# Solution (1) - this is the most obvious solution.. 
XML::xmlToDataFrame(doc) 
# Solution (2) - apparently converting to a list is also possible.. 
unlist(xmlToList(doc)) 
# Solution (3) - My own solution 
data.frame(as.list(unlist(xmlToList(doc)))) 

Не все решения получения желаемого результата ... В конце концов, только вариант решения (3) удовлетворяет мои потребности.

  1. Он находится в data.frame/data.table формате
  2. Он содержит все дочерний РЕБЕНОК-узлы и имеет различные имена для каждого столбца
  3. Это не «слияние» информация о ребенке -child-nodes

Тем не менее, запуск этой части кода для всех моих данных становится довольно медленным. Потребовалось 8 часов, чтобы завершить его для файла, содержащего 2290000 раз «узел Nummeraanduiding».

Вы, ребята, знаете какой-либо способ ускорить этот процесс? Может ли мой метод быть улучшен? Возможно, я пропустил какую-то полезную функцию?

+0

Вы можете сделать это с помощью xml2, например. 'library (xml2); tt%>% read_xml()%>% xml_children()%>% {setNames (xml_text (.), xml_name (.))}%>% t()%>% data.frame() ', хотя я бы на самом деле, вероятно, оставляют 't()%>% data.frame' и просто' rbind' векторы в матрицу, которая может быть преобразована в data.frame. Если вы хотите разобрать весь элемент по элементу, 'purrr' может быть очень полезным. – alistaire

ответ

0

Учитывая, что каждое поле уже на отдельной строке только grep их, читать то, что осталось с помощью read.table и конвертировать долго широкого использования tapply производить полученную матрицу (который может быть преобразован в кадр данных или данных. таблица при желании). Обратите внимание, что в read.table мы обойдем цитату, комментарий и обработку класса. Наконец, проверьте это, чтобы убедиться, что это быстрее. Пакеты не используются.

nms <- c("identificatie", "aanduidingRecordInactief", "aanduidingRecordCorrectie", 
"huisnummer", "officieel", "postcode", "tijdvakgeldigheid.begindatumTijdvakGeldigheid", 
"inOnderzoek", "typeAdresseerbaarObject", "bron.documentdatum", 
"bron.documentnummer", "nummeraanduidingStatus", 
"gerelateerdeOpenbareRuimte.identificatie") 

rx <- paste(nms, collapse = "|") 
g <- chartr("<", ">", grep(rx, readLines(textConnection(tt)), value = TRUE)) 

long <- read.table(text = g, sep = ">", quote = "", comment.char = "", 
    colClasses = "character")[2:3] 
names(long) <- c("field", "value") 
long$field <- factor(long$field, levels = nms) # maintain order of columns 
long$recno <- cumsum(long$field == "identificatie") 

with(long, tapply(value, list(recno, field), c)) 

Если все записи имеют точно такой же набор полей, такие как те, которые перечислены в nms, то последняя строка может быть заменена с этим (что, вероятно, быстрее):

matrix(long$value, ncol = length(nms), byrow = TRUE, dimnames = list(NULL, nms)) 

Другим вариантом к линии tapply было бы использовать reshape из базы R или использовать dcast из пакета reshape2.

Смежные вопросы