2014-09-27 2 views
9

Hat jemand einen Vorschlag für den besten Weg, um die XML-Daten auf der Website unten zu öffnen, um es in einen Datenrahmen (ich arbeite lieber mit Pandas) in Python? Die Datei befindet sich auf der „Data - XML ​​(SDMX/zip)“ Link auf dieser Seite:Wie öffne ich diese XML-Datei, um einen Datenrahmen in Python zu erstellen?

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

Ich habe folgendes versucht, mit durch das Kopieren von http://timhomelab.blogspot.com/2014/01/how-to-read-xml-file-into-dataframe.html, und es scheint, ich bin immer in der Nähe:

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) 

Noch weiß ich nicht genug über XML, um mich den Rest des Weges zu bekommen.

Jede Hilfe wäre genial - ich brauche nicht einmal brauchen es in einem Datenrahmen zu sein, ich muss nur herausfinden, wie dieser Inhalt in Python irgendwie zu analysieren.

+0

Mögliches Duplikat von [Wie kann ich eine Excel-Datei in Python öffnen?] (Http://stackoverflow.com/questions/3239207/how-can-i-open-an-excel-file-in-python) – poolie

Antwort

6

Ich würde die XLS formatted file in eine CSV-Datei exportieren (mit einem frei verfügbaren Programm wie Gnumeric oder LibreOffice, oder wenn Sie es haben, Excel), und lesen Sie dann die CSV-Datei in Pandas. Ich weiß, dass dies nicht genau eine Antwort auf Ihre letzte Frage ist, aber das Analysieren von XML ist eine übermäßig komplizierte Lösung für das, was Sie versuchen zu tun.

In Bezug auf die Analyse von XML in Python, ist die LXML-Bibliothek meine Lieblingsbibliothek zu verwenden. Ich finde die Verwendung der XPath-Abfragesprache zusammen mit einem lxml-Parser als beste Route.

8

XML ist eine baumartige Struktur, während ein Pandas DataFrame eine 2D-Tabellenstruktur ist. Es gibt also keine automatische Möglichkeit, zwischen den beiden zu konvertieren. Sie müssen die XML-Struktur verstehen und wissen, wie Sie ihre Daten einer 2D-Tabelle zuordnen wollen. So ist jedes XML-zu-DataFrame-Problem anders.

Ihr XML verfügt über 2 DataSets, die jeweils eine Reihe von Serien enthalten. Jede Serie enthält eine Anzahl von Obs-Elementen.

Jede Serie verfügt über ein NAME-Attribut, und jede Ob-Eigenschaft hat die Attribute OBS_STATUS, TIME_PERIOD und OBS_VALUE. Vielleicht wäre es also sinnvoll, eine Tabelle mit den Spalten NAME, OBS_STATUS, TIME_PERIOD und OBS_VALUE zu erstellen.

Ich fand das Ziehen der gewünschten Daten aus dem XML ein wenig kompliziert, was mich zweifelhaft macht, dass ich den besten Weg gefunden habe, es zu tun. Aber hier ist ein Weg (PS Thomas Maloney Idee mit den 2D-tabellenartigen XLS Daten beginnen, sollten Art und Weise einfacher sein.):

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) 

Ausbeuten

  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 
-1

Dieser Code verwandelt sie arbeiten, um df diese Art von Excel-XML-Datei:

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() 

ich kann nicht Kommentar (niedrige Ruf), aber die Antwort auf diese Frage zum Thema „How to open Excel XML file programmatically“ (mit python und Pandas) sollte es funktionieren.

+0

Dies gibt keine Antwort auf die Frage. Um einen Autor zu kritisieren oder um Klärung zu bitten, hinterlasse einen Kommentar unter seinem Beitrag - du kannst deine eigenen Beiträge jederzeit kommentieren, und sobald du genügend [Reputation] (http://stackoverflow.com/help/whats-reputation) hast, wirst du das tun in der Lage sein [jeden Beitrag kommentieren] (http://stackoverflow.com/help/privileges/comment). – UmNyobe

+0

@UmNyobe Ok, ich habe den Code hinzugefügt. Ich ändere gerade den Dateinamen und die Nummer der Reihe, in der die Daten beginnen. – jrovegno

Verwandte Themen