将一对多的 Pandas 数据框连接为 JSON 而不是 Pandas 数据框

3

I have 2 pandas dataframes:

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'}]}
]

有什么优雅的方式可以做到这一点?我可以先进行联接,然后再进行分组,但这样就无法确定哪些列属于外部 dep,哪些列属于 emps...

1个回答

2

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

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
@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 中每个部门只出现一次,而不是像你建议的那样每个员工都出现一次。 - ihadanny
酷!按所有有趣的部门列进行分组是我们前进的方式。 - ihadanny

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接