【问题标题】:one-to-many joining pandas dataframes as a JSON instead of a pandas dataframe以 JSON 代替 pandas 数据帧的一对多连接 pandas 数据帧
【发布时间】:2018-10-26 05:52:50
【问题描述】:

我有 2 个熊猫数据框:

dept = pd.DataFrame({'dep_id': [1,2], 'dep_name':['shoes', 'giraffes']})
emp = pd.DataFrame({'dep_id': [1,1,2], 'emp_name': ['joe', 'bo', 'gigi']})

按照关系连接的惯例,加入它们会为 emp 中的每一行重复 dept 行:

pd.merge(dept, emp, on = 'dep_id')

dep_id  dep_name emp_name
0       1     shoes      joe
1       1     shoes       bo
2       2  giraffes     gigi

相反,我想创建一个分层 JSON:例如

[ 
{ dep_name: 'shoes', emps: [{emp_name: 'joe'}, {emp_name: 'bo'}]},
{ dep_name: 'giraffes', emps: [{emp_name: 'gigi'}]}
]

什么是优雅的方法?我可以加入,然后 groupby,但是无法分辨哪些列去外部部门,哪些去 emps...

【问题讨论】:

    标签: python json pandas dataframe join


    【解决方案1】:

    一种可能的解决方案是在apply 中为emps 的DataFrames 列表定义列:

    d = (pd.merge(dept, emp, on = 'dep_id')
          .groupby('dep_name').apply(lambda x: x[['emp_name']]
          .to_dict('r'))
          .reset_index(name='emps'))
    
    print (d)
       dep_name                                       emps
    0  giraffes                     [{'emp_name': 'gigi'}]
    1     shoes  [{'emp_name': 'joe'}, {'emp_name': 'bo'}]
    
    
    j = d.to_json(orient='records')
    print (j)
    [{"dep_name":"giraffes","emps":[{"emp_name":"gigi"}]},
      {"dep_name":"shoes","emps":[{"emp_name":"joe"},{"emp_name":"bo"}]}]
    
    d = (pd.merge(dept, emp, on = 'dep_id')
          .groupby('dep_name').apply(lambda x: x[['emp_name', 'dep_id']]
          .to_dict('r'))
          .reset_index(name='emps'))
    
    print (d)
       dep_name                                               emps
    0  giraffes                [{'dep_id': 2, 'emp_name': 'gigi'}]
    1     shoes  [{'dep_id': 1, 'emp_name': 'joe'}, {'dep_id': ...
    
    j = d.to_json(orient='records')
    print (j)
    [{"dep_name":"giraffes","emps":[{"dep_id":2,"emp_name":"gigi"}]},
      {"dep_name":"shoes","emps":[{"dep_id":1,"emp_name":"joe"},{"dep_id":1,"emp_name":"bo"}]}]
    

    编辑1:

    我认为对于所有从嵌套 json 转换出来的列都需要:

    dept = pd.DataFrame({'dep_id': [1,2], 'dep_name':['shoes', 'giraffes'], 'def_size':[4,5]})
    emp = pd.DataFrame({'dep_id': [1,1,2], 'emp_name': ['joe', 'bo', 'gigi']})
    
    df = pd.merge(dept, emp, on = 'dep_id')
    #single columns def_size and dep_name
    d = (df.groupby(['def_size','dep_name']).apply(lambda x: x[['emp_name']]
          .to_dict('r'))
          .reset_index(name='emps'))
    print (d)
       def_size  dep_name                                       emps
    0         4     shoes  [{'emp_name': 'joe'}, {'emp_name': 'bo'}]
    1         5  giraffes                     [{'emp_name': 'gigi'}]
    
    j = d.to_json(orient='records')
    print (j)
    [{"def_size":4,"dep_name":"shoes","emps":[{"emp_name":"joe"},{"emp_name":"bo"}]},
      {"def_size":5,"dep_name":"giraffes","emps":[{"emp_name":"gigi"}]}] 
    

    【讨论】:

    • 哇!如果部门有其他属性,例如dep_size?我必须按所有部门列分组吗?
    • @ihadanny - 用于merge 的新列,例如pd.merge(dept, emp, on = ['dep_id', 'dep_size'])?或者需要将x[['emp_name', 'dep_id']] 更改为x[['emp_name', 'dep_size']]
    • 没有@jezrael,dep_size 不用于连接,只需要dep_id。我希望它每个部门只出现在 json 中一次,而不是你建议的每个 emp 一次
    • 酷!然后 groupby 所有有趣的部门列就是我们要走的路
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2019-06-27
    • 2020-09-02
    • 1970-01-01
    • 1970-01-01
    • 2013-12-05
    • 2018-10-27
    相关资源
    最近更新 更多