¿Cómo abrir este archivo XML para crear un dataframe en Python?

¿Alguien tiene alguna sugerencia sobre la mejor manera de abrir los datos xml en el sitio a continuación para colocarlos en un dataframe (prefiero trabajar con pandas) en python? El archivo se encuentra en el enlace “Datos – XML ​​(sdmx / zip)” en este sitio:

http://www.federalreserve.gov/pubs/feds/2006/200628/200628abs.html

He intentado usar lo siguiente copiando desde http://timhomelab.blogspot.com/2014/01/how-to-read-xml-file-into-dataframe.html , y parece que me estoy acercando:

from lxml import objectify import pandas as pd path = 'feds200628.xml' xml = objectify.parse(open(path)) root = xml.getroot() root.getchildren()[0].getchildren() df = pd.DataFrame(columns=('id', 'name')) for i in range(0,4): obj = root.getchildren()[i].getchildren() row = dict(zip(['id', 'name'], [obj[0].text, obj[1].text])) row_s = pd.Series(row) row_s.name = i df = df.append(row_s) 

Aún así, no sé lo suficiente sobre xml para conseguirme el rest del camino.

Cualquier ayuda sería increíble. Ni siquiera la necesito para estar en un dataframe, solo necesito averiguar cómo analizar este contenido en Python de alguna manera.

XML es una estructura similar a un árbol, mientras que Pandas DataFrame es una estructura similar a una tabla 2D. Así que no hay una forma automática de convertir entre los dos. Debe comprender la estructura XML y saber cómo desea asignar sus datos a una tabla 2D. Por lo tanto, cada problema de XML a DataFrame es diferente.

Su XML tiene 2 conjuntos de datos, cada uno con una serie de series. Cada serie contiene una serie de elementos Obs.

Cada serie tiene un atributo NOMBRE, y cada Obs tiene atributos OBS_STATUS, TIME_PERIOD y OBS_VALUE. Por lo tanto, tal vez sería razonable crear una tabla con las columnas NAME, OBS_STATUS, TIME_PERIOD y OBS_VALUE.

Encontré que sacar los datos deseados del XML es un poco complicado, lo que me hace dudar de haber encontrado la mejor manera de hacerlo. Pero aquí hay una forma (la idea de PS. Thomas Maloney de comenzar con los datos XLS tipo tabla 2D debería ser mucho más simple):

 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) 

rendimientos

  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 

Exportaría el archivo con formato XLS a un archivo CSV (usando un progtwig disponible gratuitamente como Gnumeric o LibreOffice, o si lo tiene, Excel), y luego leería el archivo CSV en pandas. Sé que esto no es exactamente una respuesta a tu pregunta final, pero analizar XML es una solución demasiado complicada para lo que estás tratando de hacer.

Con respecto al análisis de XML en Python, la biblioteca lxml es mi biblioteca favorita para usar. Encuentro que usar el lenguaje de consulta XPath junto con un analizador lxml es la mejor ruta.

Este código funciona para transformar en este tipo de archivo XML de Excel:

 import pandas as pd from xml.sax import ContentHandler, parse # Reference https://goo.gl/KaOBG3 class ExcelHandler(ContentHandler): def __init__(self): self.chars = [ ] self.cells = [ ] self.rows = [ ] self.tables = [ ] def characters(self, content): self.chars.append(content) def startElement(self, name, atts): if name=="Cell": self.chars = [ ] elif name=="Row": self.cells=[ ] elif name=="Table": self.rows = [ ] def endElement(self, name): if name=="Cell": self.cells.append(''.join(self.chars)) elif name=="Row": self.rows.append(self.cells) elif name=="Table": self.tables.append(self.rows) excelHandler = ExcelHandler() parse('feds200628.xls', excelHandler) df1 = pd.DataFrame(excelHandler.tables[0][10:], columns=excelHandler.tables[0][9]) print df1.head() 

No puedo hacer comentarios (baja reputación), pero la respuesta a esta pregunta sobre ” Cómo abrir Excel XML mediante progtwigción ” (con Python y Pandas) debería funcionar.