XML jest strukturą przypominającą drzewo, podczas gdy Pandas DataFrame jest strukturą przypominającą tabelę 2D. Więc nie ma automatycznego sposobu na konwersję między tymi dwoma. Musisz zrozumieć strukturę XML i wiedzieć, jak chcesz zmapować swoje dane na tabelę 2D. Tak więc każdy problem XML-to-DataFrame jest inny.
Twój XML ma 2 zestawy danych, z których każdy zawiera serię. Każda Seria zawiera wiele elementów Obs.
Każda seria ma atrybut NAME, a każdy z atrybutów Obs ma OBS_STATUS, TIME_PERIOD i OBS_VALUE. Być może rozsądnie byłoby utworzyć tabelę z kolumnami NAME, OBS_STATUS, TIME_PERIOD i OBS_VALUE.
Znalazłem wyciągając pożądane dane z XMLa nieco skomplikowane, co sprawia, że wątpię, że znalazłem najlepszy sposób to zrobić. Ale tutaj jest jeden sposób (PS pomysł Thomasa Maloney z dnia począwszy od tabelarycznego danych XLS 2D powinny być sposób prostszy.):
import lxml.etree as ET
import pandas as pd
path = 'feds200628.xml'
def fast_iter(context, func, *args, **kwargs):
"""
http://lxml.de/parsing.html#modifying-the-tree
Based on Liza Daly's fast_iter
http://www.ibm.com/developerworks/xml/library/x-hiperfparse/
See also http://effbot.org/zone/element-iterparse.htm
http://stackoverflow.com/a/7171543/190597 (unutbu)
"""
for event, elem in context:
func(elem, *args, **kwargs)
# It's safe to call clear() here because no descendants will be
# accessed
elem.clear()
# Also eliminate now-empty references from the root node to elem
for ancestor in elem.xpath('ancestor-or-self::*'):
while ancestor.getprevious() is not None:
del ancestor.getparent()[0]
del context
data = list()
obs_keys = ['OBS_STATUS', 'TIME_PERIOD', 'OBS_VALUE']
columns = ['NAME'] + obs_keys
def process_obs(elem, name):
dct = elem.attrib
# print(dct)
data.append([name] + [dct[key] for key in obs_keys])
def process_series(elem):
dct = elem.attrib
# print(dct)
context = ET.iterwalk(
elem, events=('end',),
tag='{http://www.federalreserve.gov/structure/compact/common}Obs'
)
fast_iter(context, process_obs, dct['SERIES_NAME'])
def process_dataset(elem):
nsmap = elem.nsmap
# print(nsmap)
context = ET.iterwalk(
elem, events=('end',),
tag='{{{prefix}}}Series'.format(prefix=elem.nsmap['kf'])
)
fast_iter(context, process_series)
with open(path, 'rb') as f:
context = ET.iterparse(
f, events=('end',),
tag='{http://www.federalreserve.gov/structure/compact/common}DataSet'
)
fast_iter(context, process_dataset)
df = pd.DataFrame(data, columns=columns)
plony
NAME OBS_STATUS TIME_PERIOD OBS_VALUE
0 SVENY01 A 1961-06-14 2.9825
1 SVENY01 A 1961-06-15 2.9941
2 SVENY01 A 1961-06-16 3.0012
3 SVENY01 A 1961-06-19 2.9949
4 SVENY01 A 1961-06-20 2.9833
5 SVENY01 A 1961-06-21 2.9993
6 SVENY01 A 1961-06-22 2.9837
...
1029410 TAU2 A 2014-09-19 3.72896779
1029411 TAU2 A 2014-09-22 3.12836171
1029412 TAU2 A 2014-09-23 3.20146575
1029413 TAU2 A 2014-09-24 3.29972110
Możliwy duplikat [Jak mogę otworzyć plik Excela w Pythonie?] (Http://stackoverflow.com/questions/3239207/how-can-i-open-an-excel-file-in-python) – poolie