web-dev-qa-db-ja.com

このXMLファイルを開いてPythonでデータフレームを作成するにはどうすればよいですか?

以下のサイトでxmlデータを開いてPythonのデータフレーム(パンダでの作業を好む)に配置するための最良の方法について誰かが提案していますか?このファイルは、このサイトの「データ-XML(sdmx/Zip)」リンクにあります。

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

http://timhomelab.blogspot.com/2014/01/how-to-read-xml-file-into-dataframe.html からコピーして、以下を使用してみましたが、どうやら私は近づいています:

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)

それでも、私はxmlについて十分に知らないので、残りの道を進むことができません。

どんな助けも素晴らしいでしょう-私も必要それがデータフレームにある必要はありません、私はpythonでこのコンテンツを解析する方法をどうにかして理解する必要があります。

9
SarahB87

XMLはツリーのような構造ですが、Pandas DataFrameは2Dテーブルのような構造です。したがって、2つの間で自動的に変換する方法はありません。XML構造を理解し、知っている必要があります。データを2Dテーブルにどのようにマッピングするか。したがって、XMLからDataFrameへの問題はすべて異なります。

XMLには2つのデータセットがあり、それぞれに多数のシリーズが含まれています。各シリーズには、いくつかのObs要素が含まれています。

各シリーズにはNAME属性があり、各ObsにはOBS_STATUS、TIME_PERIOD、およびOBS_VALUE属性があります。したがって、NAME、OBS_STATUS、TIME_PERIOD、およびOBS_VALUE列を使用してテーブルを作成することはおそらく合理的です。

XMLから目的のデータを引き出すのは少し複雑で、それを行うための最良の方法を見つけたのではないかと疑っています。しかし、ここに1つの方法があります(PS。ThomasMaloneyの2DテーブルのようなXLSデータから始めるという考えははるかに単純なはずです):

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)

収量

            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
9
unutbu

XLS形式のファイル をCSVファイルにエクスポートし(GnumericやLibreOfficeなどの無料で入手可能なプログラムを使用するか、Excelを使用している場合)、CSVファイルをパンダに読み込みます。これがあなたの最後の質問に対する正確な答えではないことを私は知っていますが、XMLの解析は、あなたがやろうとしていることに対する非常に複雑な解決策です。

PythonでのXMLの解析に関しては、lxmlライブラリが私のお気に入りのライブラリです。 XPathクエリ言語をlxmlパーサーと一緒に使用するのが最適なルートだと思います。

6
Thomas Maloney