Python pandas groupby和映射值列表
有两个数据帧, 其中,第一个数据框包含单元格和人名列表。 第二个数据帧包含要映射到的实际值 df1: df2: 这就是我想要的,我想从df2中提取大提琴元素的值,并将它们添加回df1 预期结果: df1:Python pandas groupby和映射值列表,python,pandas,dataframe,Python,Pandas,Dataframe,有两个数据帧, 其中,第一个数据框包含单元格和人名列表。 第二个数据帧包含要映射到的实际值 df1: df2: 这就是我想要的,我想从df2中提取大提琴元素的值,并将它们添加回df1 预期结果: df1: 有人能帮我得到这个或提出更好的解决方案吗?IIUC,您只需要将列表或NaN中的值分组,所以: # create DataFrame to check which values of cell are in Group res = df2.merge(df1, on='Name', how='r
有人能帮我得到这个或提出更好的解决方案吗?IIUC,您只需要将列表或NaN中的值分组,所以:
# create DataFrame to check which values of cell are in Group
res = df2.merge(df1, on='Name', how='right').explode('Group')
# create mask
mask = res['Group'].eq(res['cell']) | res['cell'].isna()
# filter, group by, agg and rename
output = res[mask].groupby('Name', sort=False).agg({'Group': list, 'value': list}).rename(
columns={'value': 'Group Name'})
print(output)
输出
Group Group Name
Name
Bob [a, v] [4.0, 8.0]
April [b, c] [9.0, 1.0]
Amy [v] [2.0]
Linda [g, r] [nan, nan]
更新
为了保持原始列表顺序,您可以添加一个附加步骤:
# create DataFrame to check which values of cell are in Group
res = df1.merge(df2, on='Name', how='left').explode('Group', ignore_index=True)
# reorder DataFrame to keep original list order
res['ord'] = np.arange(len(res))
res['ord'] = res.groupby(['Name', 'Group'])['ord'].transform('first')
res = res.sort_values(by='ord').drop('ord', 1)
# create mask
mask = res['Group'].eq(res['cell']) | res['cell'].isna()
# filter, group by, agg and rename
output = res[mask].groupby('Name', sort=False).agg({'Group': list, 'value': list}).rename(
columns={'value': 'Group Name'})
print(output)
我相信上述Dani方法中的几个步骤是可以真正避免的。 不需要创建遮罩。 如果在合并前将输入数据帧调平,则可以更好更快地解决问题。任何不需要匹配的键都会在较大的数据帧中被忽略,中间结果会尽可能精简
# Assuming df as first dataframe and df2 as larger 2nd dataframe
df.explode('celllist').merge(
df2, how='left',
left_on=['Name', 'celllist'],
right_on=['Name', 'cell']
).drop(columns=['cell']).groupby('Name', sort=False).agg(
{'celllist': list, 'value': list}).rename(
columns={'celllist': 'Group', 'value': 'Group Name'})
这将产生OP所需的输出
输出:
Group Group Name
Name
Bob [a, v] [4.0, 8.0]
April [b, c] [9.0, 1.0]
Amy [v] [2.0]
Linda [g, r] [nan, nan]
你想画什么。您是否正在尝试从df2获取df1和groupby结果?你期望的结果是什么?我已经编辑了这个问题。公布了预期结果。我没有做任何连接。只是在df2中按名称分组。在此之后,我无法继续。df2.groupby()将提供您发布的结果。你想用这个做什么?处理df1和df2后的预期输出是什么。无法理解下一步要做什么。在df2中完成grouby之后,我在“cell”和“value”列中列出了值列表。我希望df1中“value”列的这些值用于相应的“Group”列元素。感谢您的解决方案。对于大型数据集,合并是否需要时间?如果需要,您可以创建索引以加速合并。我认为这里的一些步骤是不必要的,只是计算开销。我在回答中提到了这一点。@anjali看到了更新的完美。谢谢。:)很酷。如果解决了你的问题,你应该接受一个解决方案。这两个解决方案对我都有效。但是我也可以在df1上有多个列,除了名称和单元格列表之外,还有一个固定的字符串,它不应该在任何时候改变,比如df1['r']='r'。这两种情况的输出都不提供df1上的额外列(r),如果它最初确实存在的话。如果我尝试将outputdf与原始df1合并,则会出现错误“TypeError:Unhable type:'list'”。该错误可能是由于在列上进行了合并,包括
组
,该列是一个列表。要与原始表合并,只有Name
列就足够了,因为它已经在Name
级别聚合,并且保证所有行都有唯一的Name
。因此,如果您注意到,Name
也是聚合数据帧中的索引。
# create DataFrame to check which values of cell are in Group
res = df1.merge(df2, on='Name', how='left').explode('Group', ignore_index=True)
# reorder DataFrame to keep original list order
res['ord'] = np.arange(len(res))
res['ord'] = res.groupby(['Name', 'Group'])['ord'].transform('first')
res = res.sort_values(by='ord').drop('ord', 1)
# create mask
mask = res['Group'].eq(res['cell']) | res['cell'].isna()
# filter, group by, agg and rename
output = res[mask].groupby('Name', sort=False).agg({'Group': list, 'value': list}).rename(
columns={'value': 'Group Name'})
print(output)
# Assuming df as first dataframe and df2 as larger 2nd dataframe
df.explode('celllist').merge(
df2, how='left',
left_on=['Name', 'celllist'],
right_on=['Name', 'cell']
).drop(columns=['cell']).groupby('Name', sort=False).agg(
{'celllist': list, 'value': list}).rename(
columns={'celllist': 'Group', 'value': 'Group Name'})
Group Group Name
Name
Bob [a, v] [4.0, 8.0]
April [b, c] [9.0, 1.0]
Amy [v] [2.0]
Linda [g, r] [nan, nan]