Python pandas groupby和映射值列表

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

有两个数据帧, 其中,第一个数据框包含单元格和人名列表。 第二个数据帧包含要映射到的实际值

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