Эффективный анализ несогласованности XML в pandas dataframe

56
6

этот вопрос касается разбора несогласованного XML со следующей структурой

<items>
<item>
<propertyA>1</propertyA>
<propertyB>B</propertyB>
<propertyC>2017</propertyC>
</item>
<item>
<propertyB>BB</propertyB>
<propertyD>D-2017</propertyD>
</item>
<item>
<propertyE>E</propertyE>
<propertyF>11:25</propertyF>
</item>
</items>

Где бы я хотел, чтобы каждый элемент был записью в dataframe. Конечный фрейм данных должен иметь все свойства A, B, C, D, E, F, а записи должны иметь NaN или что-то еще, если они не имеют этих значений.

То, как я это делаю сейчас, - это

def load_inconsistent_xml(xml):
root = ET.fromstring(xml)
frames = []
df = pd.DataFrame()
for child in root.iter('item'):
record = []
headers = []
for subchild in child:
headers.append(subchild.tag)
record.append(subchild.text)

s2 = pd.Series(record, index=headers)
df = df.append(s2, ignore_index=true)

if not df.empty:
df.columns = df.columns.str.lower()
return df

Как вы наверняка видите, я делаю это, добавляя новые pd.Series в dataframe. Подход кажется пуленепробиваемым (по крайней мере для меня: D), и я получаю свои данные согласованными.

Проблема в том, что она очень неэффективна с 100 тыс. Элементов, и длится долгое время. Чтобы вы посоветовали?

Спасибо, что уделили мне время. Я новичок в python, поэтому я буду благодарен за ваше терпение.

спросил(а) 2017-08-21T22:11:00+03:00 2 года, 3 месяца назад
1
Решение
78

Рассмотрите возможность добавления фреймов данных вместо рядов с помощью pd.concat (быстрый метод pd.concat строк/столбцов), который, если столбцы из списка данных не выравниваются, заполняет NAN. Кроме того, ниже выполняется различный синтаксический анализ со списком словарей, которые итеративно передаются в dataframe:

import xml.etree.ElementTree as ET
import pandas as pd

xml_str = '''
<items>
<item>
<propertyA>1</propertyA>
<propertyB>B</propertyB>
<propertyC>2017</propertyC>
</item>
<item>
<propertyB>BB</propertyB>
<propertyD>D-2017</propertyD>
</item>
<item>
<propertyE>E</propertyE>
<propertyF>11:25</propertyF>
</item>
</items>'''

dfs = []

def load_inconsistent_xml(xml):
data = []; inner = {}

root = ET.fromstring(xml)
for child in root.iterfind('item'):
for grandchild in child.iterfind('./*'):
inner[grandchild.tag] = grandchild.text

data.append(inner)
dfs.append(pd.DataFrame(data))
data = []; inner = {}

finaldf = pd.concat(dfs).reset_index(drop=True)
print(finaldf)

# propertyA propertyB propertyC propertyD propertyE propertyF
# 0 1 B 2017 NaN NaN NaN
# 1 NaN BB NaN D-2017 NaN NaN
# 2 NaN NaN NaN NaN E 11:25

ответил(а) 2017-08-22T00:39:00+03:00 2 года, 3 месяца назад
Ваш ответ
Введите минимум 50 символов
Чтобы , пожалуйста,
Выберите тему жалобы:

Другая проблема