You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何用Pandas按多列分组并将关联target字段加入min/max列

解决Pandas分组后关联target字段并格式化输出的问题

需求说明

按source、type列分组,计算每组similarity字段的min、max值,将对应target字段内容与min/max值拼接为「Target: [target值] ([similarity数值])」格式。

原始数据

data = [
    {'source': 'Person1', 'target': 'Person2', 'type': 'bow', 'similarity': 0.636},
    {'source': 'Person1', 'target': 'Person2', 'type': 'bigram', 'similarity': 0.040},
    {'source': 'Person1', 'target': 'Person2', 'type': 'tfidf', 'similarity': 0.433},
    {'source': 'Person1', 'target': 'Person3', 'type': 'bow', 'similarity': 0.699},
    {'source': 'Person1', 'target': 'Person3', 'type': 'bigram', 'similarity': 0.171},
    {'source': 'Person1', 'target': 'Person3', 'type': 'tfidf', 'similarity': 0.522}
]

当前问题

已通过df = df.groupby(['source','type']).similarity.agg(['min','max'])得到分组后的min/max值,但无法关联对应target字段并拼接成指定格式,询问是否需要用.loc定位后拼接或有其他更优方法。

解决方案

不需要单独用.loc循环定位,以下几种方法均可高效实现需求:

方法1:使用groupby.apply自定义处理每组

通过自定义函数处理每个分组,直接提取对应target并格式化输出:

import pandas as pd

df = pd.DataFrame(data)

def process_group(group):
    # 获取分组内similarity最小的行
    min_row = group.loc[group['similarity'] == group['similarity'].min()]
    # 获取分组内similarity最大的行
    max_row = group.loc[group['similarity'] == group['similarity'].max()]
    # 返回格式化后的结果
    return pd.Series({
        'min': f"Target: {min_row['target'].iloc[0]} ({min_row['similarity'].iloc[0]})",
        'max': f"Target: {max_row['target'].iloc[0]} ({max_row['similarity'].iloc[0]})"
    })

# 分组处理并生成结果
result = df.groupby(['source', 'type']).apply(process_group)
print(result)

方法2:自定义函数配合agg实现

为agg方法传递自定义函数,直接在聚合时完成格式化:

import pandas as pd

df = pd.DataFrame(data)

def format_min(group):
    min_sim = group['similarity'].min()
    target = group.loc[group['similarity'] == min_sim, 'target'].iloc[0]
    return f"Target: {target} ({min_sim})"

def format_max(group):
    max_sim = group['similarity'].max()
    target = group.loc[group['similarity'] == max_sim, 'target'].iloc[0]
    return f"Target: {target} ({max_sim})"

# 聚合时调用自定义函数
result = df.groupby(['source', 'type']).agg(
    min=('similarity', format_min),
    max=('similarity', format_max)
)
print(result)

方法3:通过transform标记极值行再合并

先标记每组的min/max行,再合并数据后格式化:

import pandas as pd

df = pd.DataFrame(data)

# 标记每组内similarity最小/最大的行
df['is_min'] = df['similarity'] == df.groupby(['source', 'type'])['similarity'].transform('min')
df['is_max'] = df['similarity'] == df.groupby(['source', 'type'])['similarity'].transform('max')

# 提取min和max对应的数据
min_data = df[df['is_min']][['source', 'type', 'target', 'similarity']].rename(columns={'target': 'min_target', 'similarity': 'min_sim'})
max_data = df[df['is_max']][['source', 'type', 'target', 'similarity']].rename(columns={'target': 'max_target', 'similarity': 'max_sim'})

# 合并数据并格式化输出
result = pd.merge(min_data, max_data, on=['source', 'type'])
result['min'] = result.apply(lambda x: f"Target: {x['min_target']} ({x['min_sim']})", axis=1)
result['max'] = result.apply(lambda x: f"Target: {x['max_target']} ({x['max_sim']})", axis=1)

# 整理最终结果格式
result = result[['source', 'type', 'min', 'max']].set_index(['source', 'type'])
print(result)

输出示例

三种方法最终输出结果一致,格式如下:

min                  max
source  type                                
Person1 bigram  Target: Person2 (0.04)  Target: Person3 (0.171)
        bow     Target: Person2 (0.636) Target: Person3 (0.699)
        tfidf   Target: Person2 (0.433) Target: Person3 (0.522)

内容的提问来源于stack exchange,提问作者MartinCodes

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.08 15:25:15