带有嵌套字典的 Pandas DataFrame

Posted

技术标签:

【中文标题】带有嵌套字典的 Pandas DataFrame【英文标题】:Pandas DataFrame w/nested dictionary 【发布时间】:2020-02-18 20:58:42 【问题描述】:

在查看SO 上的类似问题后,我一直无法找到使用嵌套字典对 DataFrame 格式化的解决方案,以获得所需的结果。

作为 Pandas 的新手和 Python 的新手,我花了两天的大部分时间尝试各种潜在的解决方案,但都失败了(json_normalize、dictionary flattening、pd.concat 等)。

我有一个从 API 调用创建 DataFrame 的方法:

def make_dataframes(self):
    # removed non-related code    
    self._data_frame_counts = pd.DataFrame(
            'Created': (self._data_frame_30days.count()['Created']),
            'Closed': (self._data_frame_30days.count()['Closed']),
            'Owner':
            (self._data_frame_30days['Owner'].value_counts().to_dict()),
            'Resolution':
            (self._data_frame_30days['Resolution'].value_counts().to_dict()),
            'Severity':
            (self._data_frame_30days['Severity'].value_counts().to_dict())
        )

从 Pandas value_count/s 写入嵌套字典:

'Created': 35,
 'Closed': 6,
 'Owner': 'aName': 30, 'first.last': 3, 'last.first': 2,
 'Resolution': 'TruePositive': 5, 'FalsePositive': 1,
 'Severity': 2: 31, 3: 4

执行后的样子:

                  Created Closed  Owner  Resolution  Severity
aName             35       6     30.0         NaN       NaN
first.last        35       6      3.0         NaN       NaN
last.first        35       6      2.0         NaN       NaN
TruePositive      35       6      NaN         5.0       NaN
FalsePositive     35       6      NaN         1.0       NaN
2                 35       6      NaN         NaN      31.0
3                 35       6      NaN         NaN       4.0

我希望它看起来像下面这样。数据与轴准确对齐并说明字典中不存在但可能在未来运行中存在的缺失数据点。

                Created Closed  Owner   Resolution  Severity
total           35      6       NaN     NaN         NaN
aName           NaN     NaN     30      NaN         NaN
first.last      NaN     NaN     3       NaN         NaN
last.first      NaN     NaN     2       NaN         NaN
anotherName     NaN     NaN     NaN     NaN         NaN
1               NaN     NaN     NaN     NaN         0
2               NaN     NaN     NaN     NaN         31
3               NaN     NaN     NaN     NaN         4
second.Name     NaN     NaN     NaN     NaN         NaN
third.name      NaN     NaN     NaN     NaN         NaN
TruePositive    NaN     NaN     NaN     5           NaN
FalsePositive   NaN     NaN     NaN     1           NaN

【问题讨论】:

【参考方案1】:

假设我有一本字典 d

d = 
    'Created': 35,
    'Closed': 6,
    'Owner': 'aName': 30, 'first.last': 3, 'last.first': 2,
    'Resolution': 'TruePositive': 5, 'FalsePositive': 1,
    'Severity': 2: 31, 3: 4


我会创建一些额外的键

_d = 
    'Created': 'total': d['Created'],
    'Closed': 'total': d['Closed'],
    'Severity': k: d['Severity'].get(k, 0) for k in range(1, 4)


pd.DataFrame(**d, **_d)

               Created  Closed  Owner  Resolution  Severity
total             35.0     6.0    NaN         NaN       NaN
aName              NaN     NaN   30.0         NaN       NaN
first.last         NaN     NaN    3.0         NaN       NaN
last.first         NaN     NaN    2.0         NaN       NaN
TruePositive       NaN     NaN    NaN         5.0       NaN
FalsePositive      NaN     NaN    NaN         1.0       NaN
1                  NaN     NaN    NaN         NaN       0.0
2                  NaN     NaN    NaN         NaN      31.0
3                  NaN     NaN    NaN         NaN       4.0

这是我更新你的一些密钥的方式,我们可以看到我做了什么:

print(_d)

'Created': 'total': 35, 'Closed': 'total': 6, 'Severity': 0: 0, 2: 31, 3: 4

默认情况下,pandas.DataFrame 构造函数可以采用字典并将键用作列名。它对值的作用取决于这些值。

如果该值是一个标量,它会为所有索引值广播该标量。 (这就是您在 'Created' 列中的所有行中看到的重复 35。 如果该值是一个类似数组的东西,那么该东西的长度会更好地匹配行数,因为它将逐个元素地将该数组插入到列中。 如果值是字典,它会将每个键/值对映射到键为索引值的列中。

最后一项是我回答的动机。我将35 的标量值更改为我指定索引值'total': 35 的字典


我建议把原来的方法改成这样:

def make_dataframes(self):
    # removed non-related code    
    counts = self._data_frame_30days['Severity'].value_counts().to_dict()
    self._data_frame_counts = pd.DataFrame(
            'Created': 'total': self._data_frame_30days.count()['Created'],
            'Closed': 'total': self._data_frame_30days.count()['Closed'],
            'Owner':
            (self._data_frame_30days['Owner'].value_counts().to_dict()),
            'Resolution':
            (self._data_frame_30days['Resolution'].value_counts().to_dict()),
            'Severity': k: counts.get(k, 0) for k in sorted(k, *counts)
        )

【讨论】:

以上是关于带有嵌套字典的 Pandas DataFrame的主要内容,如果未能解决你的问题,请参考以下文章

将带有嵌套字典的json响应转换为pandas数据框[重复]

如何合并两个数据框? [复制]

用 Pandas 数据框中的行填充嵌套字典

嵌套字典到 MultiIndex pandas DataFrame(3 级)

来自 Python 嵌套字典的 Pandas Dataframe

来自嵌套字典的 Pandas 数据框