【问题标题】:Parsing inconsistent XML into pandas dataframe efficiently有效地将不一致的 XML 解析为 pandas 数据帧
【发布时间】:2017-08-21 19:11:56
【问题描述】:

这个问题是关于解析具有以下结构的不一致 XML

<items>
<item>
    <propertyA>1</propertyA>
    <propertyB>B</propertyB>
    <propertyC>2017</propertyC>
</item>
<item>
    <propertyB>BB</propertyB>
    <propertyD>D-2017</propertyD>
</item>
<item>
    <propertyE>E</propertyE>
    <propertyF>11:25</propertyF>
</item>
</items>

我希望每个项目成为数据框中的记录。最终数据框应具有所有属性 A、B、C、D、E、F,并且记录应具有 NaN 或其他属性,以防它们没有这些值。

我现在的做法是

def load_inconsistent_xml(xml):
root = ET.fromstring(xml)
frames = []
df = pd.DataFrame()
for child in root.iter('item'):
    record = []
    headers = []
    for subchild in child:
        headers.append(subchild.tag)
        record.append(subchild.text)

    s2 = pd.Series(record, index=headers)
    df = df.append(s2, ignore_index=true)

if not df.empty:
    df.columns = df.columns.str.lower()
return df

您肯定可以看到,我通过将新的 pd.Series 附加到数据框来做到这一点。这种方法似乎是防弹的(至少对我来说:D),而且我的数据是一致的。

问题是,100k 个项目的效率非常低,需要很长时间。 你会推荐什么?

感谢您花时间回答我的问题。我是 python 新手,感谢您的耐心等待。

【问题讨论】:

    标签: python xml pandas xml-parsing


    【解决方案1】:

    考虑使用pd.concat(一种快速的行/列绑定方法)附加数据帧而不是系列,如果数据帧列表中的列不对齐,则会填充 NAN。此外,下面会运行一个不同的解析,其中包含一个迭代地转换为数据框的字典列表:

    import xml.etree.ElementTree as ET
    import pandas as pd
    
    xml_str = '''
    <items>
    <item>
        <propertyA>1</propertyA>
        <propertyB>B</propertyB>
        <propertyC>2017</propertyC>
    </item>
    <item>
        <propertyB>BB</propertyB>
        <propertyD>D-2017</propertyD>
    </item>
    <item>
        <propertyE>E</propertyE>
        <propertyF>11:25</propertyF>
    </item>
    </items>'''
    
    dfs = []
    
    def load_inconsistent_xml(xml):        
        data = []; inner = {}
    
        root = ET.fromstring(xml)        
        for child in root.iterfind('item'):
            for grandchild in child.iterfind('./*'):            
                inner[grandchild.tag] = grandchild.text
    
            data.append(inner)
            dfs.append(pd.DataFrame(data))
            data = []; inner = {}
    
        finaldf = pd.concat(dfs).reset_index(drop=True)
        print(finaldf)
    
    #   propertyA propertyB propertyC propertyD propertyE propertyF
    # 0         1         B      2017       NaN       NaN       NaN
    # 1       NaN        BB       NaN    D-2017       NaN       NaN
    # 2       NaN       NaN       NaN       NaN         E     11:25
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2019-08-17
      • 2018-04-08
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2020-03-24
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多