Считать отсутствующие теги XML как 0 или NA?

У меня есть несколько XML-документов со следующей структурой:

read_xml(filename, sep = "")) %>% xml_find_all("//_atraso") %>% xml_structure

[[1]]
<_atraso>
  <_omsmaximodia [_omsmaximodia]>
  <_omsmaximo [_omsmaximo]>
  <_omsmedia [_omsmedia]>
  ...
...

[[32]]
<_atraso>
  <_omsmaximo [_omsmaximo]>
  <_omsmedia [_omsmedia]>
  ...

Как можно видеть, родительский тег _atraso имеет дочерний тег _omsmaximodia на некоторых элементах, но не на других (в этом случае в индексе 1 дочерний тег присутствует, а в индексе 32 его нет).

Я хочу прочитать значение _omsmaximodia, если оно присутствует, и 0 или NA в противном случае. Сейчас читаю вот так:

omsmaximodia <- read_xml(filename, sep = "")) %>% xml_find_all("//_omsmaximodia") %>% xml_attr("_omsmaximodia") %>% gsub("\\.","",.) %>% gsub(",",".",.) %>% {as.numeric(.)}

Однако он ничего не читает, когда тег _omsmaximodia отсутствует. Выполнение приведенного выше кода приводит к списку длиной 29, потому что только 29 из 32 элементов имеют тег _omsmaximodia. Мне нужна длина 32, чтение 0 или NA, где его нет.

Я мог бы легко добавить в список NA или 0, но порядок, в котором элементы читаются, имеет значение. То есть, если элемент 30 не имеет тега _omsmaximodia, тогда значение в позиции 30 в списке должно быть NA или 0. Простое добавление 0 или NA в конец списка недопустимо.

Я попытался использовать функции xml_missing и xml_has_attr, чтобы выяснить, какие индексы не содержат тега _omsmaximodia, но эти функции, похоже, не указывают на отсутствующие теги, и я не смог определить индекс, по которому они отсутствуют.

Любые идеи?

У меня была аналогичная проблема, и я выбрал purrr::map вместо элементов с чем-то вроде xml %>% map(xml_find_all, "//_omsmaximodia"), но это, очевидно, немного неэффективно. Было бы любопытно, есть ли лучшее решение ...

Thomas K 14.05.2018 17:33

Вероятно, вы можете сделать это в двух частях: сначала найдите все узлы _atraso, а затем найдите _omsmaximodia индивидуально внутри каждого из них.

Luis 14.05.2018 17:35
Стоит ли изучать PHP в 2026-2027 годах?
Стоит ли изучать PHP в 2026-2027 годах?
Привет всем, сегодня я хочу высказать свои соображения по поводу вопроса, который я уже много раз получал в своем сообществе: "Стоит ли изучать PHP в...
Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
В JavaScript одним из самых запутанных понятий является поведение ключевого слова "this" в стрелочной и обычной функциях.
Приемы CSS-макетирования - floats и Flexbox
Приемы CSS-макетирования - floats и Flexbox
Здравствуйте, друзья-студенты! Готовы совершенствовать свои навыки веб-дизайна? Сегодня в нашем путешествии мы рассмотрим приемы CSS-верстки - в...
Тестирование функциональных ngrx-эффектов в Angular 16 с помощью Jest
В системе управления состояниями ngrx, совместимой с Angular 16, появились функциональные эффекты. Это здорово и делает код определенно легче для...
Концепция локализации и ее применение в приложениях React ⚡️
Концепция локализации и ее применение в приложениях React ⚡️
Локализация - это процесс адаптации приложения к различным языкам и культурным требованиям. Это позволяет пользователям получить опыт, соответствующий...
Пользовательский скаляр GraphQL
Пользовательский скаляр GraphQL
Листовые узлы системы типов GraphQL называются скалярами. Достигнув скалярного типа, невозможно спуститься дальше по иерархии типов. Скалярный тип...
1
2
140
1
Перейти к ответу Данный вопрос помечен как решенный

Ответы 1

Ответ принят как подходящий

Чтобы сохранить структуру вашего xml-документа, вы можете попробовать применить свою функцию ко всем элементам отдельно. Следующий пример иллюстрирует составленные данные, поскольку вы только набросали структуру данных.

# load packages and read data
library(xml2)
library(purrr)

input <- "<xml>
  <_atraso>
    <_omsmaximodia></_omsmaximodia>
  </_atraso>
  <_atraso>
  </_atraso>
</xml>"

x <- read_xml(input)
x
#> {xml_document}
#> <xml>
#> [1] <_atraso>\n  <_omsmaximodia/>\n</_atraso>
#> [2] <_atraso>\n  </_atraso>

Мы можем найти интересующий тег, но при обычном подходе мы не получаем пропущенного значения для второго тега:

x %>% 
  xml_find_all(".//_omsmaximodia")
#> {xml_nodeset (1)}
#> [1] <_omsmaximodia/>

Чтобы решить эту проблему, мы переходим на один уровень глубже с xml_children, а затем отображаем все элементы. Результатом для второго элемента является пустой набор узлов. Мы можем использовать map_if в сочетании с is_empty, чтобы преобразовать его в пропущенные значения.

x %>% 
  xml_children() %>% 
  map(xml_find_all, ".//_omsmaximodia") %>% 
  map_if (is_empty, ~{.x <- NA}) 
#> [[1]]
#> {xml_nodeset (1)}
#> [1] <_omsmaximodia/>
#> 
#> [[2]]
#> [1] NA

В зависимости от того, что вам нужно сделать, вы можете использовать различные функции для сглаживания или изменения структуры списка.

Обратите внимание, что с этим кодом вторая версия примерно в 4 раза медленнее. Если вы сделаете это несколько раз, это не имеет значения (второй запрос занимает около 0,75 мс, по сравнению с 0,2 мс для первого), но если вы делаете это часто (т. Е. Анализируете много документов), это может сложиться.

Другие вопросы по теме