0

0

标题:Pandas 数据对比分析:按区域层级统计客户变动并汇总明细名单

心靈之曲

心靈之曲

发布时间:2026-01-13 17:29:18

|

536人浏览过

|

来源于php中文网

原创

标题:Pandas 数据对比分析:按区域层级统计客户变动并汇总明细名单

本文详解如何使用 pandas 对两个时间点的客户数据进行对比,按 zone/region/district 三级分组,精准计算客户流入、流出、新增、流失数量,并完整列出对应客户姓名清单。

在客户运营或区域管理场景中,常需对比不同时期的客户分布变化,尤其当客户归属存在跨区迁移(如从 A2b 迁至 A2a)、新增入驻或完全退出时,仅统计数量远远不够——业务人员更需要知道“谁来了”“谁走了”“谁转到了哪里”。本文提供一套完整、可复用的 pandas 实现方案,基于 df1(期初快照)和 df2(期末快照),输出包含 13 列的结构化变动报告,其中关键难点在于 将客户姓名聚合为列表并按三级地理维度对齐

核心思路:分四类客户分别处理,再统一合并

我们把客户变动划分为四类逻辑明确的群体:

Elser AI Comics
Elser AI Comics

一个免费且强大的AI漫画生成工具,助力你三步创作自己的一出好戏

下载
  • Transfer In(转入):同一客户在 df2 中出现在新区域(与 df1 的 Zone/Region/District 不同);
  • Transfer Out(转出):同一客户在 df1 中的原属区域(即其“离开地”);
  • Leaver(流失客户):存在于 df1 但完全不在 df2 中的客户;
  • New Customer(新增客户):存在于 df2 但完全不在 df1 中的客户。
⚠️ 注意:merge(on='cust_name') 是关键前提——它要求 cust_name 具有唯一性且能稳定标识同一客户。若实际数据中存在重名风险,建议改用 cust_id 作为主键(修改 on='cust_id' 并同步调整列引用)。

完整实现代码(含注释与健壮性增强)

import pandas as pd
import numpy as np

# 构建示例数据(与问题一致)
df1 = pd.DataFrame({
    'cust_name': ['cxa', 'cxb', 'cxc', 'cxd', 'cxe', 'cxf'],
    'cust_id': ['c1001', 'c1002', 'c1003', 'c1004', 'c1006', 'c1007'],
    'town_id': ['t001', 't002', 't001', 't003', 't002', 't002'],
    'Zone': ['A', 'A', 'A', 'B', 'A', 'A'],
    'Region': ['A1', 'A2', 'A1', 'B1', 'A2', 'A2'],
    'District': ['A1a', 'A2a', 'A1a', 'B1a', 'A2b', 'A2b']
})

df2 = pd.DataFrame({
    'cust_name': ['cxb', 'cxc', 'cxd', 'cxe', 'cxf'],
    'cust_id': ['c1002', 'c1003', 'c1004', 'c1006', 'c1007'],
    'town_id': ['t002', 't001', 't003', 't002', 't002'],
    'Zone': ['A', 'A', 'A', 'A', 'C'],
    'Region': ['A2', 'A1', 'A1', 'A2', 'C1'],
    'District': ['A2a', 'A1a', 'A1a', 'A2a', 'C1a']
})

# 步骤1:识别迁移客户(同一客户,区域变化)
merged = df1.merge(df2, on='cust_name', suffixes=('_df1', '_df2'), how='inner')
# 判断是否发生跨区变动(任一地理层级不同即视为迁移)
merged['is_moved'] = (
    (merged['Zone_df1'] != merged['Zone_df2']) |
    (merged['Region_df1'] != merged['Region_df2']) |
    (merged['District_df1'] != merged['District_df2'])
)
moved = merged[merged['is_moved']].copy()

# 步骤2:提取转入 & 转出名单(按目标/源区域分组)
transfer_in = moved[['Zone_df2', 'Region_df2', 'District_df2', 'cust_name']].rename(
    columns={'Zone_df2': 'Zone', 'Region_df2': 'Region', 'District_df2': 'District', 'cust_name': 'NamesTransferIn'}
)
transfer_out = moved[['Zone_df1', 'Region_df1', 'District_df1', 'cust_name']].rename(
    columns={'Zone_df1': 'Zone', 'Region_df1': 'Region', 'District_df1': 'District', 'cust_name': 'NamTransferOut'}
)

# 步骤3:按三级分组聚合姓名列表(自动去重,保留顺序)
def collect_names(series):
    return list(series)  # 若需去重:list(series.unique())

in_agg = transfer_in.groupby(['Zone', 'Region', 'District'])['NamesTransferIn'].apply(collect_names).reset_index()
out_agg = transfer_out.groupby(['Zone', 'Region', 'District'])['NamTransferOut'].apply(collect_names).reset_index()

# 步骤4:合并转入/转出(outer join 确保所有变动区域不遗漏)
result = pd.merge(in_agg, out_agg, on=['Zone', 'Region', 'District'], how='outer').fillna('')

# 步骤5:添加流失客户(df1有、df2无)
leavers = df1[~df1['cust_name'].isin(df2['cust_name'])][['cust_name', 'Zone', 'Region', 'District']]
leavers_agg = leavers.groupby(['Zone', 'Region', 'District'])['cust_name'].apply(collect_names).reset_index().rename(columns={'cust_name': 'NamLeaver'})
result = pd.merge(result, leavers_agg, on=['Zone', 'Region', 'District'], how='outer').fillna('')

# 步骤6:添加新增客户(df2有、df1无)
new_customers = df2[~df2['cust_name'].isin(df1['cust_name'])][['cust_name', 'Zone', 'Region', 'District']]
new_agg = new_customers.groupby(['Zone', 'Region', 'District'])['cust_name'].apply(collect_names).reset_index().rename(columns={'cust_name': 'NamNewCustomer'})
result = pd.merge(result, new_agg, on=['Zone', 'Region', 'District'], how='outer').fillna('')

# ✅ 最终结果:已包含全部13列中的姓名字段(其余数值列可基于此表用 groupby.size() 补全)
print(result[
    ['Zone', 'Region', 'District', 
     'NamesTransferIn', 'NamTransferOut', 'NamLeaver', 'NamNewCustomer']
])

关键注意事项与优化建议

  • 空值处理:使用 .fillna('') 将 NaN 替换为空字符串,避免后续 JSON 序列化或 Excel 导出报错;若需保留 None,可改用 fillna(pd.NA)。
  • 姓名去重:若同一客户因数据质量问题重复出现,可在 collect_names() 中加入 series.unique()。
  • 扩展数值列:本教程聚焦姓名字段,但 Initial Count / Final Count 等可通过 df1.groupby(['Zone','Region','District']).size() 和 df2.groupby(...).size() 快速生成,再 merge 进 result。
  • 性能提示:对百万级数据,避免 apply(lambda x: ...),优先使用向量化操作;merge 前确保 cust_name 列已设为索引或启用 sort=False。
  • 输出增强:可调用 result.to_excel("customer_movement_report.xlsx", index=False) 直接导出带格式报表。

通过该方案,你不仅获得结构清晰的变动摘要,更掌握了以客户实体为中心、支持业务溯源的精细化分析能力——让每一条数据变动都“有据可查、有人可溯”。

相关专题

更多
json数据格式
json数据格式

JSON是一种轻量级的数据交换格式。本专题为大家带来json数据格式相关文章,帮助大家解决问题。

411

2023.08.07

json是什么
json是什么

JSON是一种轻量级的数据交换格式,具有简洁、易读、跨平台和语言的特点,JSON数据是通过键值对的方式进行组织,其中键是字符串,值可以是字符串、数值、布尔值、数组、对象或者null,在Web开发、数据交换和配置文件等方面得到广泛应用。本专题为大家提供json相关的文章、下载、课程内容,供大家免费下载体验。

532

2023.08.23

jquery怎么操作json
jquery怎么操作json

操作的方法有:1、“$.parseJSON(jsonString)”2、“$.getJSON(url, data, success)”;3、“$.each(obj, callback)”;4、“$.ajax()”。更多jquery怎么操作json的详细内容,可以访问本专题下面的文章。

309

2023.10.13

go语言处理json数据方法
go语言处理json数据方法

本专题整合了go语言中处理json数据方法,阅读专题下面的文章了解更多详细内容。

74

2025.09.10

Python 时间序列分析与预测
Python 时间序列分析与预测

本专题专注讲解 Python 在时间序列数据处理与预测建模中的实战技巧,涵盖时间索引处理、周期性与趋势分解、平稳性检测、ARIMA/SARIMA 模型构建、预测误差评估,以及基于实际业务场景的时间序列项目实操,帮助学习者掌握从数据预处理到模型预测的完整时序分析能力。

51

2025.12.04

counta和count的区别
counta和count的区别

Count函数用于计算指定范围内数字的个数,而CountA函数用于计算指定范围内非空单元格的个数。本专题为大家提供相关的文章、下载、课程内容,供大家免费下载体验。

197

2023.11.20

sort排序函数用法
sort排序函数用法

sort排序函数的用法:1、对列表进行排序,默认情况下,sort函数按升序排序,因此最终输出的结果是按从小到大的顺序排列的;2、对元组进行排序,默认情况下,sort函数按元素的大小进行排序,因此最终输出的结果是按从小到大的顺序排列的;3、对字典进行排序,由于字典是无序的,因此排序后的结果仍然是原来的字典,使用一个lambda表达式作为key参数的值,用于指定排序的依据。

385

2023.09.04

js 字符串转数组
js 字符串转数组

js字符串转数组的方法:1、使用“split()”方法;2、使用“Array.from()”方法;3、使用for循环遍历;4、使用“Array.split()”方法。本专题为大家提供js字符串转数组的相关的文章、下载、课程内容,供大家免费下载体验。

254

2023.08.03

php与html混编教程大全
php与html混编教程大全

本专题整合了php和html混编相关教程,阅读专题下面的文章了解更多详细内容。

1

2026.01.13

热门下载

更多
网站特效
/
网站源码
/
网站素材
/
前端模板

精品课程

更多
相关推荐
/
热门推荐
/
最新课程
Excel 教程
Excel 教程

共162课时 | 11.6万人学习

成为PHP架构师-自制PHP框架
成为PHP架构师-自制PHP框架

共28课时 | 2.4万人学习

关于我们 免责申明 举报中心 意见反馈 讲师合作 广告合作 最新更新
php中文网:公益在线php培训,帮助PHP学习者快速成长!
关注服务号 技术交流群
PHP中文网订阅号
每天精选资源文章推送

Copyright 2014-2026 https://www.php.cn/ All Rights Reserved | php.cn | 湘ICP备2023035733号