
本文详解如何在 pandas 中对 DataFrame 按 org_id 分组,对指定列(如 location_id、street_x)执行「去重 + 竖线分隔」聚合,同时安全处理缺失值与数据类型问题,避免 FutureWarning。
本文详解如何在 pandas 中对 dataframe 按 `org_id` 分组,对指定列(如 `location_id`、`street_x`)执行「去重 + 竖线分隔」聚合,同时安全处理缺失值与数据类型问题,避免 futurewarning。
在实际数据分析中,常需将具有相同主键(如 org_id)的多条记录合并为单行,并对非键字段进行定制化聚合——例如将地址、ID 等文本型字段去重后以 | 连接。但直接使用 .agg() 配合 x.unique() 易触发 FutureWarning,根本原因在于:pandas 在调用 .unique() 时,若列中存在 NaN 或混合类型(如 object 中混有 datetime64、None),会导致部分列聚合失败;此外,.unique() 返回的数组元素类型可能不支持 str.join()(如 Timestamp、NaT 或 NoneType)。
正确做法是:为每列显式指定聚合函数,并确保输入经类型清洗与空值过滤。以下为推荐实现方案:
✅ 推荐写法:按列定制聚合逻辑
import pandas as pd
import numpy as np
# 定义安全的去重拼接函数(兼容 NaN 和多种数据类型)
def join_unique_safe(series):
# 去除 NaN/None,转为字符串,再去重,最后拼接
cleaned = series.dropna().astype(str).unique()
return ' | '.join(cleaned) if len(cleaned) > 0 else ''
# 指定各列聚合方式:关键列(如 org_name, category)通常取首值(assume consistent)
# 可变列(如 location_id, street_x)使用自定义拼接
agg_dict = {
'org_name': 'first',
'category': 'first',
'org_status': 'first',
'created_on': 'first',
'modified_on': 'first',
'location_id': join_unique_safe,
'loc_status': 'first', # 若该列在同 org_id 下恒为 'ACTIVE',取 first 即可
'street_x': join_unique_safe,
'city': 'first',
'country': 'first'
}
df_grouped = df.groupby('org_id', as_index=False).agg(agg_dict)⚠️ 关键注意事项
- 勿全局复用单一 lambda:原错误代码 df.groupby(...).agg(join_unique) 试图对所有列统一应用同一函数,但 created_on 是 datetime64 类型,x.unique().astype(str) 会将其转为 ISO 字符串(如 '2016-10-18 15:38:34.322000'),虽能运行但语义失真;而 loc_status 若含 NaN 则 dropna().astype(str) 会跳过它,但若全为 NaN 则返回空字符串——这比抛异常更隐蔽。因此,务必按列语义分别定义聚合逻辑。
- 'first' vs 'last' vs 'min'/'max':对时间戳(created_on)、状态码等一致性高的字段,优先用 'first';若需最新修改时间,则对 modified_on 用 'max'。
- 空值鲁棒性:join_unique_safe 中 dropna() 是必须步骤,否则 np.nan 传入 str() 会生成 'nan' 字符串,污染结果(如 'LOC-100052061 | nan')。
- 性能提示:对大数据集,避免在 agg() 中频繁调用 astype(str);可预先清洗:df[['location_id', 'street_x']] = df[['location_id', 'street_x']].astype(str)。
? 验证输出示例
运行上述代码后,输入中两条 ORG-100023310 记录将合并为一行,其中:
- location_id → 'LOC-100052061 | LOC-100032442'
- street_x → 'Fraunhoferstrasse 9a, Martinsried | Lochhamer Strasse 29a, Martinsried'
- 其余列保留首个出现的值(如 org_name 仍为 'advanceCOR GmbH')
此方法兼顾准确性、可读性与健壮性,是生产环境中处理“一对多”文本聚合的标准实践。










