2017-08-10 166 views
1

對於你們中的一些人來說,這可能是一個簡單的問題。Python Pandas:在迭代器上使用map函數

我正在解析一個XML樹,它有一個相當複雜和嵌套的結構。這是部分代碼:

import xml.etree.ElementTree as ET 
import pandas as pd 
from bs4 import BeautifulSoup as BS 

tree = ET.parse('input_data.xml') 
root = tree.getroot() 

for unit in root.iter('xml_element_name'): 
    # do something with the unit 

但我想擺脫的,每次迭代的,因爲我想用一個地圖功能(如Pandas.Series.map或Pandas.Dataframe.map或任何類似的)。所以這是我想實現的僞代碼:

items = pd.Series(root.iter('xml_element_name')) 
df = pd.Dataframe(items.map(lambda unit: ....)) 

但是怎麼樣?任何想法?

PS:tutorial of the ElementTree中可以找到示例XML。

爲什麼我想這樣做?因爲我想稍後切換到PySpark,所以每個XMLElement(unit)都是並行處理的。

回答

1

你可以嘗試創建一個平面數據結構到迭代器的通過:

flat_list = list(root.iter()) 

,然後創建一個數據框出來。

下面是完整的片段:

import xml.etree.ElementTree as ET 
import pandas as pd 
from bs4 import BeautifulSoup as BS 
import pdb 

tree = ET.parse('cd_catalog.xml') 
root = tree.getroot() 

flat_list = list(root.iter()) 
df  = pd.DataFrame({'xml_elements':flat_list}) 

# do some arbitrary computation on the df: 
result = df.xml_elements.map(lambda x: x.text) 
print(result.head(n=3)) 

(鏈接到xml file

+0

This works 。即使在第一次運行中分割第一個元素(層次結構)是一個好主意。這意味着在調用root.iter()時可以獲得多個列,從而創建字典或系列。 – Matthias

1

沒有任何藉口讓你知道你正在解析的文檔的結構。通過您引用的示例,您可以使用列表和字典解析的組合將某些內容傳遞給pd.DataFrame構造函數。

希望這個給你和想法

pd.DataFrame([ 
    {a.tag: a.text for a in c if a.tag != 'neighbor'} 
    for c in root.findall('country') 
]) 

    gdppc rank year 
0 141100 1 2008 
1 59900 4 2011 
2 13600 68 2011 
+0

不是一個簡單的代碼。特別是您使用的數據框的構造器。但我明白我猜。備註:我解析的XML有點複雜。 btw:你的代碼仍然在構造函數中使用for-each。 – Matthias

+0

@Matthias,但總的來說,理解似乎更快。同樣的,'地圖'也是一樣。 – piRSquared

+0

我結束了使用你的代碼,而上面的另一個工作。 'df = pd.DataFrame([(child.tag,child.attrib)for root.iter('country')])''''''df.columns = ['tag','attributes']' – Matthias