次のXMLファイルを変換したい:
<data>
<level_1 name="employment">
<level_2 name="sub-employment">
<indicator>ind1</indicator>
<indicator>ind2</indicator>
</level_2>
<level_2 name="sub-employment2">
<indicator>ind3</indicator>
</level_2>
</level_1>
<level_1 name="health">
<level_2 name="sub-health">
<level_3 name="sub-sub-health">
<indicator>ind4</indicator>
</level_3>
</level_2>
</level_1>
</data>
Pandasデータフレームに変換すると、次のような結果になります。
level_1 level_2 level_3 indicator
0 employment sub-employment None ind1
1 employment sub-employment None ind2
2 employment sub-employment2 None ind3
3 health sub-health sub-sub-health ind4
xml.etree.cElementTreeをetとしてインポートし、pandasをpdとしてインポートした後、次のコードを使用しました。
def getvalueofnode(node):
""" return node text or None """
return node.text if node is not None else None
def main():
""" main """
parsed_xml = et.parse("tree.xml")
dfcols = ['level_1', 'level_2', 'level_3', 'indicator']
df_xml = pd.DataFrame(columns=dfcols)
for node in parsed_xml.getroot():
name = node.attrib.get('name')
level_2 = node.find('level_2')
level_3 = node.find('level_3')
indicator = node.find('indicator')
df_xml = df_xml.append(
pd.Series([name, getvalueofnode(level_2), getvalueofnode(level_3),
getvalueofnode(indicator)], index=dfcols),
ignore_index=True)
print(df_xml)
main()
しかし、私は間違った結果を得ています:
level_1 level_2 level_3 indicator
0 employment \n None None
1 health \n None None
私はここで何が間違っているのですか?
次の関数を定義し、ノードから上に向かって祖先のディクショナリを作成します。
def parNames(node, root):
names = {}
while True:
node = parentMap[node]
if node is root:
return names
names[node.tag] = node.attrib['name']
後で必要になります。間もなく作成されるparentMap辞書を使用します。
入力ファイルを読み取ります。
tree = et.parse('tree.xml')
root = tree.getroot()
実際の処理は、親マップ(辞書)の作成から開始する必要があります。辞書は、ノードごとに親を返します。
parentMap = {}
for parent in root.iter():
for child in parent:
parentMap[child] = parent
DataFrameのソースデータを作成するには、次のコマンドを実行します。
rows = []
for it in root.iter('indicator'):
row = parNames(it, root)
row[it.tag] = it.text
rows.append(row)
このループは、辞書のリスト(各行のデータ)を作成します。各行(辞書)には次のものが含まれます。
次のステップは、DataFrameを作成することです。
df2 = pd.DataFrame(rows).fillna('').sort_index(axis=1)
そして、実行する唯一のステップは、インジケーター列を最後の位置に移動することです。
df2 = df2.reindex(df2.columns.drop('indicator')
.append(pd.Index(['indicator'])),axis=1)
この記事はインターネットから収集されたものであり、転載の際にはソースを示してください。
侵害の場合は、連絡してください[email protected]
コメントを追加