Используя пакет R xml2
Мне удалось проанализировать и преобразовать прикрепленный ниже XML-файл в фрейм данных.Я использую следующий код:
require(magrittr)
require(xml2)
res <- read_xml("~/xml_file.xml", as = "parsed")
vars <- res %>% xml_find_first("./d1:resultProperties") %>%
xml_children() %>% xml_text()
size <- res %>% xml_find_first("./d1:resultsInformation") %>%
xml_children() %>% xml_text() %>% as.numeric()
orgUnits <- res %>% xml_find_first("d1:results") %>%
xml_children()
В узле resultProperties можно заранее определить, какая переменная там находится;в то время как узел resultsInformation дает счет.Я использовал эту полезную информацию, когда пытался найти стратегию для преобразования ее в фрейм данных, хранящий эти значения в переменных vars и size .
Для фактического преобразования в фрейм данных я нашел два метода:
метод 1: (поскольку я знаю ex-ante включенные переменные) пересекает каждый orgUnit узел и извлекать по одной переменной за раз из каждого узла
# method 1 - extract one variable at a time from each orgUnit node
df <- data.frame(matrix(NA, nrow = size, ncol = length(vars)))
for (i in 1:length(vars)) {
df[ ,i] = xml_text(xml_find_first(orgUnits, paste0( "d1:", vars[i])))
}
метод 2: извлекать каждый узел orgUnit полностью при обходе DOM
# method 2.2
f <- function(x){
a <- xml_children(x)
text <- xml_text(a)
names(text) <- xml_name(a)
class(text) <- "list"
text
}
df <- map_dfr(orgUnits, f)
Сложность в том, что я не могу просто использовать такую функцию, как xml_find_all
, поскольку не каждый узел orgUnit содержит все переменные.И в методе 2 я должен был назначить список class =, иначе bind_rows жаловался бы.
Я довольно доволен обоими решениями: метод 2 немного быстрее, чемСпособ 1. Однако для анализа ~ 8'000 orgUnits требуемое время находится в диапазоне 4,50-6,30 секунд.Мне нужно использовать эту процедуру для большого XML-файла (~ 1'000'000 orgUnits ), и производительность действительно плохая.
Отказ от ответственности: я начинающий в том, что я объясняю ниже, пожалуйста, прости небрежную номенклатуру.
Я хотел бы использовать Rcpp
для интеграции кода C ++ в мой Rscript.Узкое место моего кода начинается, когда я извлекаю узлы orgUnits : создаваемая мной переменная orgUnits больше не является указателем (как, например, переменная res).Я полагаю, что работать с указателями гораздо быстрее, чем с объектами, подобными списку R.
Поэтому я хотел бы написать специальный код C ++, возможно, используя выражения xpath для извлечения текста из узлов.НО я совсем не уверен в C ++.У кого-нибудь есть предложения о том, как написать такой код C ++ или, возможно, написать более эффективный код R?
Большое спасибо заранее
<orgUnitsResponse>
<filters>
<nace>
<ns2:in>
<ns2:value>64_11</ns2:value>
<ns2:value>64_19</ns2:value>
</ns2:in>
</nace>
</filters>
<resultProperties>
<resultProperty>id</resultProperty>
<resultProperty>birth_date</resultProperty>
<resultProperty>close_date</resultProperty>
<resultProperty>code</resultProperty>
<resultProperty>name</resultProperty>
<resultProperty>nace</resultProperty>
<resultProperty>postal_code</resultProperty>
<resultProperty>city</resultProperty>
</resultProperties>
<resultsInformation>
<count>4</count>
</resultsInformation>
<results>
<orgUnit>
<id>1</id>
<birth_date>1998-01-01</birth_date>
<close_date>9999-12-31</close_date>
<code>AT00100</code>
<name>Oesterreichische Nationalbank</name>
<nace>64_11</nace>
<postal_code>1090</postal_code>
<city>Wien</city>
</orgUnit>
<orgUnit>
<id>128</id>
<birth_date>1998-01-01</birth_date>
<close_date>9999-12-31</close_date>
<code>AT20607</code>
<name>Sparkasse Bludenz Bank AG</name>
<nace>64_19</nace>
<postal_code>6700</postal_code>
<city>Bludenz</city>
</orgUnit>
<orgUnit>
<id>130</id>
<birth_date>1998-01-01</birth_date>
<close_date>9999-12-31</close_date>
<code>AT20702</code>
<name>Sparkasse Feldkirchen/Kärnten</name>
<nace>64_19</nace>
<postal_code>9560</postal_code>
<city>Feldkirchen (Ktn.)</city>
</orgUnit>
<orgUnit>
<id>131</id>
<birth_date>1998-01-01</birth_date>
<close_date>9999-12-31</close_date>
<code>AT20706</code>
<name>Kärntner Sparkasse Aktiengesellschaft</name>
<nace>64_19</nace>
<postal_code>9020</postal_code>
<city>Klagenfurt</city>
</orgUnit>
</results>
</orgUnitsResponse>