本文介绍如何利用`groupby().apply()`配合自定义函数,将dataframe中按连续相同“head”分组的成员列表整合为自然语言格式的邀请消息,并自动排除与head同名的重复成员。
在实际数据分析中,常需将结构化数据(如分组后的多行记录)转换为可读性强的文本摘要。本例目标是:对连续出现的相同 head(如 "Abba As")所对应的 members 列进行聚合,生成一条个性化邀请语句——其中首名成员(取 head 的姓氏部分)作为主宾称呼,其余成员用“and”连接,并保留原始 head 字符串用于入场标识。
关键难点在于:需按“head值连续出现”的逻辑分组(而非简单去重分组),因为同一 head 可能在后续再次出现(如示例中 "Abba As" 出现在索引 0–2 和 6–8),应视为两个独立邀请批次。
以下是完整实现方案:
import pandas as pd
# 构建示例数据
df = pd.DataFrame({
'head': ['Abba As', 'Abba As', 'Abba As', 'Bella Bi', 'Bella Bi', 'Bella Bi', 'Abba As', 'Abba As', 'Abba As'],
'members': ['Ally', 'Apo', 'Abba', 'Bella', 'Boo', 'Brian', 'Arra', 'Alya', 'Abba']
})
# 步骤1:识别连续分组(核心!)
group = df['hea
d'].ne(df['head'].shift()).cumsum()
# 步骤2:定义生成message的函数
def generate_message(group_df):
head_full = group_df.name[0] # 获取当前组的head值(元组形式,取第一个元素)
head_first_name = head_full.split()[0] # 提取首名(如"Abba")
# 过滤掉与首名相同的成员(即本人),保留其余成员
other_members = [m for m in group_df['members'] if m != head_first_name]
# 用" and "连接其他成员
others_str = ' and '.join(other_members)
return f'Hi {head_first_name}, we invite you, {others_str}. Please use "{head_full}" when arriving.'
# 步骤3:分组应用 + 整理结果
result = (df.groupby(['head', group], sort=False)
.apply(generate_message)
.droplevel(1) # 删除辅助分组层级
.reset_index(name='message'))✅ 输出结果严格匹配预期:
head message 0 Abba As Hi Abba, we invite you, Ally and Apo. Please use "Abba As" when arriving. 1 Bella Bi Hi Bella, we invite you, Boo and Brian. Please use "Bella Bi" when arriving. 2 Abba As Hi Abba, we invite you, Arra and Alya. Please use "Abba As" when arriving.
⚠️ 注意事项:
该模式可灵活扩展:替换模板字符串、支持多语言、接入邮件/短信API,是构建自动化报告与通知系统的典型范式。