将多层嵌套字典转换为pandas DataFrame
我正在尝试处理从Salesforce REST API返回的嵌套有序字典的查询结果,并把它们转换成pandas的DataFrame对象。不过,由于返回的字典嵌套结构不一致,我遇到了一些麻烦。
举个例子,我有一个有序字典的列表,每个字典里都有一个‘Id’,一个‘Email’,还有一个名为‘attributes’的有序字典,这个字典里包含了‘url’和‘type’:
[OrderedDict([(u'attributes', OrderedDict([(u'type', u'someType'), (u'url', u'/someurl')])), (u'Id', u'1A'), (u'Email', u'xxxx@xxxx.com')]),…]
我希望把这些数据转换成一个有序字典的列表,所有的数据字段都在同一层级上(也就是说,没有嵌套的有序字典),而‘attributes’字典里的数据也要提升到上一层:
[OrderedDict([(u'type', u'someType'), (u'url', u'/someurl'), (u'Id', u'1A'), (u'Email', u'xxxx@xxxx.com')]),…]
理想情况下,我希望能把数据格式化成一种长格式,这样无论嵌套层级有多少,都能帮助我把数据解析成更容易处理的格式(比如pandas的DataFrame)。我之前主要使用R,所以我对处理DataFrame比处理嵌套字典要更得心应手。
我尝试过很多针对类似问题的解决方案,但每个方案似乎都解决了与我情况稍有不同的问题。问题在于,我返回的数据中嵌套字典的层级数量没有一致性。如果我简单地尝试把当前的列表转换成pandas的DataFrame,我得到的结果是:
import pandas as pd
pd.DataFrame(salesRecords).head()
Email Id
0 some@email.com 1A
1 some@email.com 1B
2 some@email.com 1C
3 some@email.com 1D
4 some@email.com 1E
attributes
0 {u'type': u'someType', u'url': u'someurl...
1 {u'type': u'someType', u'url': u'someurl...
2 {u'type': u'someType', u'url': u'someurl...
3 {u'type': u'someType', u'url': u'someurl...
4 {u'type': u'someType', u'url': u'someurl...
在这个例子中,我想把‘attributes’这一列“扁平化”,变成两个包含属性数据的列(‘type’和‘url’)。如果有人能给我指个方向,我将非常感激。
非常感谢!
1 个回答
0
这是我尝试的结果:
def flatten(d):
'''
Flatten an OrderedDict object
'''
result = OrderedDict()
for k, v in d.items():
if isinstance(v, dict):
result.update(flatten(v))
else:
result[k] = v
return result
讨论
flatten
函数会创建一个新的OrderedDict
对象,也就是扁平化字典。- 它会逐个遍历每一个键值对。
- 如果某个值不是字典(包括 OrderedDict),那么就把这个键值对复制到结果里。
- 如果这个值是字典,包括 OrderedDict,那就递归调用
flatten
函数,并更新结果。 - 我测试过这个函数,能处理四层嵌套,但不能保证没有错误。
- 一旦你在一个 OrderedDict 上测试过
flatten
,那么在一系列 OrderedDict 上使用它就很简单了。