【问题标题】:Exploding multiple dict columns and concatenating with original Pandas data frame分解多个 dict 列并与原始 Pandas 数据框连接
【发布时间】:2022-11-07 09:44:55
【问题描述】:

我导出 Postgresql 查询以创建类似于以下内容的 Pandas 数据框 df

df = pd.DataFrame({
    'employee_id' : [123, 456, 789],
    'country_code' : ['US', 'CAN', 'MEX'],
    'sales' : [{'foo': 2, 'bar': 0, 'baz': 1},
               {'foo': 3, 'bar': 1, 'baz': 2},
               {'foo': 7, 'bar': 0, 'baz': 4}],
    'expenses' : [{'red': 1, 'white': 0, 'blue': 3},
               {'red': 1, 'white': 0, 'blue': 1},
               {'red': 2, 'white': 2, 'blue': 2}]
})

df
 
    employee_id   country_code      sales                             expenses
0   123           US                {'foo': 2, 'bar': 0, 'baz': 1}    {'red': 1, 'white': 0, 'blue': 3}
1   456           CAN               {'foo': 3, 'bar': 1, 'baz': 2}    {'red': 1, 'white': 0, 'blue': 1}
2   789           MEX               {'foo': 7, 'bar': 0, 'baz': 4}    {'red': 2, 'white': 2, 'blue': 2}

我希望能够爆炸两个都salesexpenses 列,以便它们的键是单独的列。目前,我只能爆炸这些列中,如下所示:

df = pd.json_normalize(df['sales'])
df
    foo bar baz
0   2   0   1
1   3   1   2
2   7   0   4

我无法将列列表传递给pd.json.normalize()

问题:

  1. 如何分解salesexpenses 列?
  2. 爆炸两列后,如何从原始数据框中添加回另外两列(employee_idcountry_code)?

    所需的输出是:

        employee_id   country_code   foo   bar   baz   red   white   blue
    0   123           US             2     0     1     1     0       3
    1   456           CAN            3     1     2     1     0       1
    2   789           MEX            7     0     4     2     2       2
    

    谢谢!

【问题讨论】:

    标签: pandas


    【解决方案1】:

    您可以将concat 沿轴=1 与json_normalize 一起使用:

    json_cols = ['sales','expenses']
    result = pd.concat([pd.json_normalize(df[col]) for col in json_cols],axis=1)
    result = pd.concat([df.drop(json_cols,axis=1),result],axis=1)
    

    输出:

    结果

        employee_id country_code    foo bar baz red white   blue
    0   123         US               2   0   1   1   0       3 
    1   456         CAN              3   1   2   1   0       1
    2   789         MEX              7   0   4   2   2       2
    

    【讨论】:

      【解决方案2】:

      如果要修改原始数据框,则变体为:

      cols = ['sales', 'expenses']
      
      df = pd.concat([df]+[pd.json_normalize(df.pop(c)) for c in cols], axis=1)
      

      输出:

         employee_id country_code  foo  bar  baz  red  white  blue
      0          123           US    2    0    1    1      0     3
      1          456          CAN    3    1    2    1      0     1
      2          789          MEX    7    0    4    2      2     2
      

      【讨论】:

        【解决方案3】:
           df.join(df.sales.apply(pd.Series))
            .join(df.expenses.apply(pd.Series))
            .drop(['sales','expenses'],axis=1)
            
            
               employee_id country_code  foo  bar  baz  red  white  blue
            0          123           US    2    0    1    1      0     3
            1          456          CAN    3    1    2    1      0     1
            2          789          MEX    7    0    4    2      2     2
        

        【讨论】:

          猜你喜欢
          • 2017-05-25
          • 2017-06-08
          • 2021-02-19
          • 2016-08-13
          • 1970-01-01
          • 2021-03-20
          • 2020-03-14
          • 1970-01-01
          相关资源
          最近更新 更多