将多层嵌套字典转换为pandas DataFrame

1 投票
1 回答
4732 浏览
提问于 2025-04-18 02:23

我正在尝试处理从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 上使用它就很简单了。

撰写回答