融化包含字典列的熊猫数据框,以便字典值也被融化

Posted

技术标签:

【中文标题】融化包含字典列的熊猫数据框,以便字典值也被融化【英文标题】:Melt pandas dataframe containing column of dictionaries such that the dictionary values are also melted 【发布时间】:2020-08-04 20:13:41 【问题描述】:

这不是重复的

这个问题:Pandas column dict split to new column and rows 没有回答这篇文章中的问题。我在这篇文章的末尾包含了一种将一列字典转换为数据框的方法,这不是我在这里发现的困难。


设置

给定以下数据:

d1 = 'a' : 12, 'b' : 44
d2 = 'this' : 9, 'that' : 33, 'there' : 82
d3 = 'x' : 19, 'y' : 38, 'z' : 12, 't' : 90
df = pd.DataFrame(dict(
    var_1 = [1,2,3],
    var_2 = ['one', 'two', 'four'],
    var_3 = [d1, d2, d3]
))

看起来像:

   var_1 var_2                                 var_3
0      1   one                    'a': 12, 'b': 44
1      2   two  'this': 9, 'that': 33, 'there': 82
2      3  four  'x': 19, 'y': 38, 'z': 12, 't': 90

我希望能够.melt,特别是id_vars,以某种方式 还从var_3 列中提取了字典。

只使用第一行:

   var_1 var_2                                 var_3
0      1   one                    'a': 12, 'b': 44

预期的中期结果是:

   var_1 var_2   key   value    
0      1   one    a     12
1      1   one    b     44

融化后是这样的:

# using df.melt(id_vars = ['var_1', 'var_2'])

   var_1 var_2 variable value
0      1   one      key     a
1      1   one      key     b
2      1   one    value    12
3      1   one    value    44

我想对所有数据执行此操作。

尝试

老实说,我很不确定该怎么做。

# make key : value dataframe
row_i = 0
col_i = 2
key_value_df = (pd.DataFrame( df.iloc[ row_i, col_i], index= [0 ]  )
                    .T.reset_index()
                    .rename(columns = 'index' : 'key', 0 : 'value')
            )

data_thing = (pd.concat( [pd.DataFrame(df.iloc[ 0 , [0,1]]
                    .to_dict(), index=[0])] * len(key_value_df) ))

然后

data_thing.join(key_value_df).reset_index(drop=True)

会给

   var_1 var_2 key  value
0      1   one   a     12
1      1   one   a     12

但这感觉它可以显着改善,我不确定是否将其推广到其他行。

编辑

我可以使用诸如

之类的东西将一列字典作为数据框
all_keys = functools.reduce(lambda x,y: x+y , [list(x.keys()) for x in var3])
all_values = functools.reduce(lambda x,y: x+y, [list(x.values()) for x in var3])
pd.DataFrame(dict( keys = all_keys, values = all_values ))

给予

    keys  values
0      a      12
1      b      44
2   this       9
3   that      33
4  there      82
5      x      19
6      y      38
7      z      12
8      t      90

但这并不能回答我提出的问题

【问题讨论】:

【参考方案1】:
def custom_melt(df):
    vals = []
    for row in df.itertuples():
        for k, v in row.var_3.items():
            vals.append('var_1': row.var_1,
                         'var_2': row.var_2,
                         'variable': 'key',
                         'value': k)
            vals.append('var_1': row.var_1,
                         'var_2': row.var_2,
                         'variable': 'value',
                         'value': v)
    return pd.DataFrame(vals).sort_values(['var_1', 'var_2', 'variable'])

输出

>>>custom_melt(df)
    var_1 var_2 variable  value
0       1   one      key      a
2       1   one      key      b
1       1   one    value     12
3       1   one    value     44

【讨论】:

使用嵌套的 for 循环,并对列名进行硬编码,让我在这里有点不安【参考方案2】:

使用您的df

import pandas as pd

var3 = pd.DataFrame(pd.DataFrame(df['var_3'].values.tolist()).stack().reset_index(level=1))
var3.columns = ['keys','values']

print(var3)

    keys    values
0   a       12.0
0   b       44.0
1   this    9.0
1   that    33.0
1   there   82.0
2   x       19.0
2   y       38.0
2   z       12.0
2   t       90.0

df = df.join(var3)

print(df)

pd.json_normalize

这可能会更好
var3 = pd.DataFrame(pd.json_normalize(df.var_3).stack()).reset_index(level=1)
var3.columns = ['keys','values']

【讨论】:

谢谢特伦顿,我刚刚意识到这是可行的,因为保留了索引值,使连接可以在以后使用它。我几乎从不这样做,所以这对我来说非常有用。干杯 :) (起初我很惊讶加入知道每个人要保留多少...) 是的,这是一个问题。每个人都想要一个漂亮的0...n 索引,但你不能join

以上是关于融化包含字典列的熊猫数据框,以便字典值也被融化的主要内容,如果未能解决你的问题,请参考以下文章

如何融化熊猫数据框?

来自数据框的嵌套字典,内部字典包含熊猫系列作为值

如何将包含元组列表的字典中的字典转换为熊猫数据框

序列化包含熊猫数据框的字典(Python)

来自熊猫数据框嵌套字典的熊猫数据框

从熊猫数据框中提取嵌套字典