如何将 XML 数据解析为 Pandas DataFrame

How Parse XML Data to Pandas Dataframe

提问人:justnewbie89 提问时间:11/14/2023 最后编辑:justnewbie89 更新时间:11/15/2023 访问量:65

问:

所以我有这种xml数据

<?xml version='1.0' encoding='UTF-8'?>
<CONSOLIDATED_LIST>
    <INDIVIDUALS>
        <INDIVIDUAL>
            <STUDENT_ID>1</STUDENT_ID>
            <FIRST_NAME>JAMES</FIRST_NAME>
            <SECOND_NAME>PETER</SECOND_NAME>
            <THIRD_NAME>SOMMER</THIRD_NAME>
            <DOB>
                <YEAR>2000</YEAR>
                <MONTH>JUNE</MONTH>
                <DATE>30</DATE>
            </DOB>
            <SCORE>
                <MATH>100</MATH>
                <PHYSICS>90</PHYSICS>
            </SCORE>
            <SCORE>
                <BIOLOGY>100</BIOLOGY>
            </SCORE>
            <SCORE>
                <Economic>100</Economic>
            </SCORE>
        </INDIVIDUAL>
        <INDIVIDUAL>
            <STUDENT_ID>2</STUDENT_ID>
            <FIRST_NAME>RICKY</FIRST_NAME>
            <SECOND_NAME>HUTTON</SECOND_NAME>
            <THIRD_NAME>LEE</THIRD_NAME>
            <DOB>
                <YEAR>2001</YEAR>
                <MONTH>MARCH</MONTH>
                <DATE>29</DATE>
            </DOB>
            <SCORE>
                <MATH>90</MATH>
                <PHYSICS>70</PHYSICS>
                <ENGLISH>70</ENGLISH>
            </SCORE>
            <SCORE>
                <Economic>100</Economic>
            </SCORE>
        </INDIVIDUAL>
    </INDIVIDUALS>
    <GROUPS>
        <GROUP>
            <GROUP_ID>1</GROUP_ID>
            <TEAM_LEADER>JAMES</TEAM_LEADER>
            <TEAM_MEMBER>PETER</TEAM_MEMBER>
        </GROUP>
    </GROUPS>

</CONSOLIDATED_LIST>

目标是在 Python Pandas 中解析这些数据,以便我可以使用这些数据进行分析。

我尝试了几种方法,但仍然不知道缺少什么。有些仅当树深度仅为 2 时才有效。有些只有在consolidated_list后只有一个分支时才有效,并且我在示例数据中找不到解析 DOB 和 SCORE 等部分的答案

期望的结果是这样的enter image description here

Pandas XML 数据帧

评论


答:

1赞 Timeless 11/14/2023 #1

一个可能的选择:

import xml.etree.ElementTree as ET

data = [] # collecting the data

for ind in ET.parse("file.xml").findall(".//INDIVIDUAL"):
    d = {}
    for c in ind:
        if not c:
            d[c.tag] = c.text
        else:
            d.setdefault(c.tag, []).append({e.tag: e.text for e in c})
    data.append(d)

# a custom func to format nested data
def joinested(lst, kv=False, sep=", "):
    # feel free to adjust the parameters
    return sep.join(f"{k}:{v}" if kv else v # << you may need to change ":"
                    for d in lst for k,v in d.items())

# making the df
df = pd.DataFrame(data)

df["DOB"] = df["DOB"].apply(lambda x: pd.to_datetime(
    joinested(x), format="%Y, %B, %d")).dt.strftime("%Y/%m/%d")
df["SCORE"] = df["SCORE"].apply(joinested, kv=True) # add `sep` if needed

输出:

STUDENT_ID FIRST_NAME SECOND_NAME THIRD_NAME 出生日期 得分
0 1 詹姆斯 彼得 索默 2000/06/30 数学:100, 物理:90, 生物:100, 经济学:100
1 2 里奇 赫顿 2001/03/29 数学:90, 物理:70, 英语:70, 经济:100

旧答案

评论

0赞 justnewbie89 11/15/2023
非常感谢,如果有另一个同名的分支怎么办,例如<score><biology>50</biology></score>
0赞 Timeless 11/15/2023
你能通过更新你的示例来将其包含在你的帖子中吗?xml
0赞 justnewbie89 11/15/2023
该帖子刚刚更新。有的学生证有 2 分分支,有的学生证有 3 分或更多。
1赞 justnewbie89 11/17/2023
它工作非常感谢