Разобрать xml с подузлами и создать фрейм данных Pandas

У меня есть следующий формат xml:

<?xml version = "1.0" encoding = "UTF-8"?>
<results>
   <run>
      <information>
         <logfile>s.log</logfile>
         <version>33</version>
         <mach>1</mach>
         <problemname>mm1</problemname>
         <timestamp>20201218.165122.053486</timestamp>
      </information>
      <controls>
         <item>VARS</item>
      </controls>
      <result>
         <status>4</status>
         <time>3</time>
         <obj>1.0</obj>
         <gap>0.15</gap>
      </result>
   </run>
</results>

У меня есть пример кода ниже, чтобы разобрать этот файл после прочтения этого поста Как преобразовать файл XML в красивый фрейм данных pandas?, но возвращает None. Однако мой вопрос заключается в том, есть ли быстрый способ создать фрейм данных, который содержит индекс из значения (т. е. VARS) и 4 столбца, т. е. статус, время, объект и разрыв.

import pandas as pd
from xml.etree import ElementTree as et

root = (et.parse('test.xml').getroot()).getchildren()


tags = {"tags":[]}
for elem in root:
    tag = {}
    tag["status"] = elem.attrib['status']
    tag["time"] = elem.attrib['time']
    tag["obj"] = elem.attrib['obj']
    tag["gap"] = elem.attrib['gap']
    tags["tags"]. append(tag)

df_users = pd.DataFrame(tags["tags"])
df_users.head()

Это результат, который я ищу:


      status  time  obj   gap
VARS  4        3    1.0   0.15

Что etree выводит для вас? Нас как бы не волнует xml, мы заботимся о выводе etree, так как это то, что вы пытаетесь создать df.

noah 22.12.2020 23:45

Ваш xml неправильно сформирован - например, где рядом <run> и <results>?

Jack Fleeting 23.12.2020 00:14

@ДжекФлитинг. Спасибо. Только что обновил это.

Alex Man 23.12.2020 00:25

@noah Спасибо, что поделились публикацией. Обновил мой вопрос в соответствии с этим.

Alex Man 23.12.2020 00:26

Попробуйте понять, почему вы получаете None. В том, что нет elem в root? Если это так, то это проблема синтаксического анализа xml. Код, касающийся создания панд, и так должен быть достаточно быстрым.

noah 23.12.2020 00:53

Можете ли вы использовать lxml вместо xml.etree? Это просто проще.

Jack Fleeting 23.12.2020 01:34

Отвечает ли это на ваш вопрос? Как преобразовать файл XML в красивый фрейм данных pandas?

iacob 21.04.2021 09:54
Почему в Python есть оператор "pass"?
Почему в Python есть оператор "pass"?
Оператор pass в Python - это простая концепция, которую могут быстро освоить даже новички без опыта программирования.
Некоторые методы, о которых вы не знали, что они существуют в Python
Некоторые методы, о которых вы не знали, что они существуют в Python
Python - самый известный и самый простой в изучении язык в наши дни. Имея широкий спектр применения в области машинного обучения, Data Science,...
Основы Python Часть I
Основы Python Часть I
Вы когда-нибудь задумывались, почему в программах на Python вы видите приведенный ниже код?
LeetCode - 1579. Удаление максимального числа ребер для сохранения полной проходимости графа
LeetCode - 1579. Удаление максимального числа ребер для сохранения полной проходимости графа
Алиса и Боб имеют неориентированный граф из n узлов и трех типов ребер:
Оптимизация кода с помощью тернарного оператора Python
Оптимизация кода с помощью тернарного оператора Python
И последнее, что мы хотели бы показать вам, прежде чем двигаться дальше, это
Советы по эффективной веб-разработке с помощью Python
Советы по эффективной веб-разработке с помощью Python
Как веб-разработчик, Python может стать мощным инструментом для создания эффективных и масштабируемых веб-приложений.
3
8
1 117
3
Перейти к ответу Данный вопрос помечен как решенный

Ответы 3

Я думаю, вам все еще нужно пройти через etree, чтобы извлечь фрагменты с помощью xml.

import pandas as pd
from xml.etree import ElementTree as et

root = et.parse('test.xml').getroot()

results = []
for ele in eles.findall('run'):
    # assumed each run contains only one control item 
    control = ele.find('controls').find('item').text
    # extract each run result and save it in the results 
    for attr in list(ele.find('result')):
        result = {}
        result['control'] = control
        result[attr.tag] = attr.text
        results.append(result)
# at last, convert into dataframe and set control as index 
results = pd.DataFrame(results)
results = results.set_index('control')

Как здесь создается "eles"?

Wev 02.08.2022 13:30
Ответ принят как подходящий

Мы можем использовать методы findall и find из ElementTree для извлечения нужных нам элементов (дочерние элементы result в качестве столбцов и controls/item в качестве индекса):

pd.DataFrame({x.tag: x.text for x in et.findall('./run/result//')},
             index = [et.find('./run/controls/item').text])

Выход:

     status time  obj   gap
VARS      4    3  1.0  0.15

Обратите внимание, что статус не находится под root, но вы пытаетесь найти его под root.

status находится под родителем result.

Вам нужно рекурсивно проверять статус под дочерними элементами.

Обратитесь к документации. Подробно рассказывается о методах с образцами. findall полезен, как предложили другие.

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