2017-08-10 167 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