开篇:从数据到洞察的最后一跃
上一节,我们完成了数据清洗,现在手上有12.5万条干净的工单数据。但这只是第一步。
数据清洗只是手段,业务洞察才是目的。
今天,我们将用这些数据回答以下业务问题:
- 哪些门店表现最好?哪些需要重点关注?
- 各战区的NPS表现如何?有什么规律?
- 保养和维修业务的客单价差异有多大?
- 周末和工作日的客流量有什么不同?
- 客户评分的影响因素是什么?
让我们开始这段从数据到洞察的旅程。
第一部分:门店维度分析
1. 计算各门店的核心指标
# 按门店分组统计
store_metrics = df_clean.groupby('门店').agg({
'order_id': 'count', # 工单数
'total_amount': 'sum', # 总营收
'rating': 'mean', # 平均评分
'customer_name': 'nunique' # 客户数(去重)
}).round(2)
# 重命名列
store_metrics.columns = ['工单数', '总营收', '平均评分', '客户数']
# 计算客单价
store_metrics['客单价'] = (store_metrics['总营收'] / store_metrics['工单数']).round(0)
# 按总营收排序
store_metrics = store_metrics.sort_values('总营收', ascending=False)
print('门店核心指标TOP10:')
print(store_metrics.head(10))
输出示例:
门店核心指标TOP10:
工单数 总营收 平均评分 客户数 客单价
上海浦东店 2845 4,280,500 4.52 1850 1504
北京朝阳店 2680 3,950,000 4.38 1720 1474
广州天河店 2520 3,780,000 4.45 1650 1500
...
2. 计算各门店的NPS
def calculate_nps(df):
"""
计算NPS分数
NPS = (推荐者数 - 贬损者数) / 总数 * 100
"""
total = len(df)
if total == 0:
return None
promoters = len(df[df['NPS分类'] == '推荐者'])
detractors = len(df[df['NPS分类'] == '贬损者'])
nps = ((promoters - detractors) / total) * 100
return round(nps, 1)
# 计算各门店NPS
store_nps = df_clean.groupby('门店').apply(calculate_nps).sort_values(ascending=False)
print('\n门店NPS排名TOP10:')
for store, nps in store_nps.head(10).items():
print(f'{store}: {nps}分')
print('\n门店NPS排名倒数10:')
for store, nps in store_nps.tail(10).items():
print(f'{store}: {nps}分')
真实洞察:
通过分析,我们发现:
- 上海浦东店NPS达到68.5分,远超行业平均水平50分
- 深圳南山店NPS仅有32.1分,需要立即介入
- NPS前10的门店,客单价平均比后10高23%
这说明:服务质量(NPS)和营收能力(客单价)强相关。
3. 门店分级与标杆识别
# 合并指标
store_full = store_metrics.copy()
store_full['NPS'] = store_nps
store_full = store_full.reset_index()
# 定义分级标准
def classify_store(row):
"""
门店分级:
A级:NPS>=60 且 总营收>=300万
B级:NPS>=50 且 总营收>=250万
C级:NPS>=40 且 总营收>=200万
D级:其他
"""
if row['NPS'] >= 60 and row['总营收'] >= 3000000:
return 'A级(标杆门店)'
elif row['NPS'] >= 50 and row['总营收'] >= 2500000:
return 'B级(优秀门店)'
elif row['NPS'] >= 40 and row['总营收'] >= 2000000:
return 'C级(合格门店)'
else:
return 'D级(需改进)'
store_full['门店等级'] = store_full.apply(classify_store, axis=1)
# 统计各等级数量
print('\n门店等级分布:')
print(store_full['门店等级'].value_counts())
# 输出标杆门店
print('\n标杆门店(A级):')
a_stores = store_full[store_full['门店等级'] == 'A级(标杆门店)']
for idx, row in a_stores.iterrows():
print(f" {row['门店']}: NPS {row['NPS']}, 营收 {row['总营收']:,.0f}元")
# 输出需改进门店
print('\n需重点关注门店(D级):')
d_stores = store_full[store_full['门店等级'] == 'D级(需改进)']
for idx, row in d_stores.iterrows():
print(f" {row['门店']}: NPS {row['NPS']}, 营收 {row['总营收']:,.0f}元")
第二部分:战区维度分析
1. 战区对比分析
# 按战区统计
region_metrics = df_clean.groupby('战区').agg({
'order_id': 'count',
'total_amount': ['sum', 'mean'],
'rating': 'mean',
'门店': 'nunique'
}).round(2)
# 扁平化列名
region_metrics.columns = ['工单总数', '总营收', '平均客单价', '平均评分', '门店数']
# 计算各战区NPS
region_nps = df_clean.groupby('战区').apply(calculate_nps)
region_metrics['NPS'] = region_nps
# 计算单店平均营收
region_metrics['单店平均营收'] = (region_metrics['总营收'] / region_metrics['门店数']).round(0)
print('战区对比分析:')
print(region_metrics.sort_values('总营收', ascending=False))
输出示例:
战区对比分析:
工单总数 总营收 平均客单价 平均评分 门店数 NPS 单店平均营收
华东战区 35680 52,450,000 1470 4.48 12 58.2 4,370,833
华南战区 28950 42,180,000 1457 4.42 10 55.8 4,218,000
华北战区 32540 46,890,000 1441 4.35 15 52.3 3,126,000
华西战区 18420 26,730,000 1451 4.40 8 54.5 3,341,250
东北战区 10257 14,850,000 1448 4.28 5 48.9 2,970,000
关键洞察:
- 华东战区表现最优
- 总营收最高:5245万
- NPS最高:58.2分
- 单店平均营收最高:437万
- 东北战区需要支持
- NPS最低:48.9分(低于行业平均50分)
- 单店平均营收最低:297万
- 建议:总部派遣华东战区标杆店店长去东北支援
2. 战区月度趋势分析
# 按战区和月份统计
region_month = df_clean.groupby(['战区', '月']).agg({
'order_id': 'count',
'total_amount': 'sum'
}).reset_index()
region_month.columns = ['战区', '月份', '工单数', '营收']
# 创建数据透视表
pivot_revenue = region_month.pivot_table(
values='营收',
index='战区',
columns='月份',
aggfunc='sum'
)
print('\n各战区月度营收对比(单位:万元):')
print((pivot_revenue / 10000).round(1))
# 计算环比增长
for region in pivot_revenue.index:
oct = pivot_revenue.loc[region, 10]
nov = pivot_revenue.loc[region, 11]
dec = pivot_revenue.loc[region, 12]
growth_nov = ((nov - oct) / oct * 100) if oct > 0 else 0
growth_dec = ((dec - nov) / nov * 100) if nov > 0 else 0
print(f'\n{region}:')
print(f' 10月→11月: {growth_nov:+.1f}%')
print(f' 11月→12月: {growth_dec:+.1f}%')
第三部分:业务类型分析
1. 保养vs维修对比
# 按服务类型统计
service_analysis = df_clean.groupby('service_type').agg({
'order_id': 'count',
'total_amount': ['sum', 'mean'],
'rating': 'mean'
}).round(2)
service_analysis.columns = ['工单数', '总营收', '平均客单价', '平均评分']
# 计算占比
service_analysis['工单占比'] = (service_analysis['工单数'] / service_analysis['工单数'].sum() * 100).round(1)
service_analysis['营收占比'] = (service_analysis['总营收'] / service_analysis['总营收'].sum() * 100).round(1)
print('保养 vs 维修对比:')
print(service_analysis)
# 计算NPS
service_nps = df_clean.groupby('service_type').apply(calculate_nps)
print('\n各服务类型NPS:')
for service, nps in service_nps.items():
print(f'{service}: {nps}分')
关键发现:
保养 vs 维修对比:
工单数 总营收 平均客单价 平均评分 工单占比 营收占比
保养 78520 98,750,000 1257 4.52 67.2% 52.8%
维修 38320 88,450,000 2308 4.18 32.8% 47.2%
各服务类型NPS:
保养: 61.5分
维修: 42.8分
洞察解读:
- 保养业务是客流基石
- 占工单数67.2%
- NPS高达61.5分
- 客户满意度稳定
- 维修业务是营收支柱
- 虽然工单数只占32.8%
- 但贡献了47.2%的营收
- 客单价是保养的1.8倍
- 维修NPS偏低是痛点
- 维修NPS只有42.8分
- 明显低于保养的61.5分
- 建议:重点提升维修服务质量和首次修复率
2. 各门店服务结构分析
# 计算各门店的保养/维修占比
store_service = df_clean.groupby(['门店', 'service_type']).agg({
'order_id': 'count',
'total_amount': 'sum'
}).reset_index()
# 创建透视表
store_service_pivot = store_service.pivot_table(
values='total_amount',
index='门店',
columns='service_type',
aggfunc='sum',
fill_value=0
)
# 计算占比
store_service_pivot['维修占比'] = (
store_service_pivot['维修'] /
(store_service_pivot['保养'] + store_service_pivot['维修']) * 100
).round(1)
print('\n各门店维修业务占比TOP10(营收占比):')
print(store_service_pivot.sort_values('维修占比', ascending=False).head(10)[['维修占比']])
print('\n各门店维修业务占比倒数10:')
print(store_service_pivot.sort_values('维修占比').head(10)[['维修占比']])
第四部分:时间维度分析
1. 工作日vs周末对比
# 按是否周末统计
weekday_analysis = df_clean.groupby('是否周末').agg({
'order_id': 'count',
'total_amount': ['sum', 'mean'],
'rating': 'mean'
}).round(2)
weekday_analysis.columns = ['工单数', '总营收', '平均客单价', '平均评分']
print('工作日 vs 周末对比:')
print(weekday_analysis)
# 计算工作日平均单日工单数
workdays = df_clean[~df_clean['是否周末']]['date_clean'].nunique()
weekends = df_clean[df_clean['是否周末']]['date_clean'].nunique()
workday_daily = weekday_analysis.loc[False, '工单数'] / workdays
weekend_daily = weekday_analysis.loc[True, '工单数'] / weekends
print(f'\n工作日平均单日工单数: {workday_daily:.0f}')
print(f'周末平均单日工单数: {weekend_daily:.0f}')
print(f'周末客流是工作日的: {(weekend_daily/workday_daily):.1%}')
洞察:
- 周末客流是工作日的1.6倍
- 但周末客单价低8%(可能因为快修快保多)
- 周末平均评分高0.15分(客户休息心情好?)
2. 月度趋势分析
# 按月份统计
month_trend = df_clean.groupby('月').agg({
'order_id': 'count',
'total_amount': 'sum',
'rating': 'mean'
}).round(2)
month_trend.columns = ['工单数', '总营收', '平均评分']
month_trend['客单价'] = (month_trend['总营收'] / month_trend['工单数']).round(0)
print('\nQ4季度月度趋势:')
print(month_trend)
# 计算环比
for i in range(11, 13):
prev_revenue = month_trend.loc[i-1, '总营收']
curr_revenue = month_trend.loc[i, '总营收']
growth = ((curr_revenue - prev_revenue) / prev_revenue * 100)
print(f'{i-1}月→{i}月营收增长: {growth:+.1f}%')
第五部分:相关性分析
1. 客单价与评分的关系
import numpy as np
# 计算相关系数
correlation = df_clean['total_amount'].corr(df_clean['rating'])
print(f'客单价与评分的相关系数: {correlation:.3f}')
if correlation > 0:
print('结论: 客单价越高,评分略有上升(正相关)')
else:
print('结论: 客单价越高,评分略有下降(负相关)')
# 按客单价分段统计评分
df_clean['客单价区间'] = pd.cut(
df_clean['total_amount'],
bins=[0, 800, 1200, 1600, 2000, 10000],
labels=['<800', '800-1200', '1200-1600', '1600-2000', '>2000']
)
price_rating = df_clean.groupby('客单价区间')['rating'].mean()
print('\n不同客单价区间的平均评分:')
for interval, rating in price_rating.items():
print(f'{interval}元: {rating:.2f}分')
2. 关键影响因素分析
# 分析影响NPS的关键因素
print('\n影响客户评分的关键因素分析:')
# 1. 服务类型的影响
print('\n1. 服务类型:')
print(df_clean.groupby('service_type')['rating'].mean())
# 2. 是否周末的影响
print('\n2. 时间因素:')
print(df_clean.groupby('是否周末')['rating'].mean())
# 3. 战区的影响
print('\n3. 战区因素:')
print(df_clean.groupby('战区')['rating'].mean().sort_values(ascending=False))
# 4. 月份的影响
print('\n4. 月份因素:')
print(df_clean.groupby('月')['rating'].mean())
第六部分:生成管理报告
1. 创建执行摘要
def generate_executive_summary(df):
"""
生成高管执行摘要
"""
total_orders = len(df)
total_revenue = df['total_amount'].sum()
avg_rating = df['rating'].mean()
overall_nps = calculate_nps(df)
stores = df['门店'].nunique()
best_store = df.groupby('门店')['total_amount'].sum().idxmax()
worst_nps_store = df.groupby('门店').apply(calculate_nps).idxmin()
summary = f"""
{'='*70}
Q4季度售后服务运营数据分析 - 执行摘要
{'='*70}
一、整体表现
• 总工单数: {total_orders:,} 单
• 总营收: ¥{total_revenue:,.0f} ({total_revenue/10000:.1f}万元)
• 平均评分: {avg_rating:.2f}/5.0
• 整体NPS: {overall_nps}分
二、门店表现
• 涉及门店数: {stores}家
• 最佳营收门店: {best_store}
• 最需关注门店: {worst_nps_store} (NPS最低)
三、核心发现
1. 华东战区表现最优,单店平均营收437万
2. 保养业务NPS达61.5分,维修业务仅42.8分
3. 周末客流是工作日的1.6倍
4. A级标杆门店占比{(df.groupby('门店').apply(calculate_nps) >= 60).sum() / stores * 100:.1f}%
四、建议行动
1. 派遣华东标杆店长支援东北战区
2. 重点提升维修服务首次修复率
3. 复制A级门店最佳实践到D级门店
4. 优化周末人员排班,提升接待能力
{'='*70}
"""
return summary
print(generate_executive_summary(df_clean))
2. 保存分析结果
# 保存各维度分析结果到Excel
with pd.ExcelWriter('Q4季度分析报告_详细数据.xlsx') as writer:
# 门店分析
store_[full.to](http://full.to)_excel(writer, sheet_name='门店分析', index=False)
# 战区分析
region_[metrics.to](http://metrics.to)_excel(writer, sheet_name='战区分析')
# 服务类型分析
service_[analysis.to](http://analysis.to)_excel(writer, sheet_name='服务类型分析')
# 时间趋势
month_[trend.to](http://trend.to)_excel(writer, sheet_name='月度趋势')
print('\n详细分析报告已保存!')
关键收获
通过这个完整的分析案例,你学会了:
✅ 多维度分析:门店、战区、业务类型、时间等
✅ 数据透视表:快速生成交叉分析表
✅ 指标计算:NPS、客单价、环比增长等
✅ 分组聚合:groupby的高级应用
✅ 相关性分析:发现变量之间的关系
✅ 洞察提取:从数据中发现业务问题和机会
✅ 报告生成:结构化的管理报告
更重要的是,你学会了如何用数据讲故事,用洞察驱动决策。
从这个案例中的深度启示
1. 数据分析的本质是回答业务问题
不要为了分析而分析。每一个数据透视表、每一张图表,都应该服务于一个明确的业务问题。
2. 好的分析要有对比
- 门店之间的对比
- 战区之间的对比
- 时间维度的对比(环比、同比)
- 细分维度的对比(保养vs维修)
有对比才有洞察,有洞察才有行动。
3. 洞察的价值在于可执行
本案例中的洞察都配有具体建议:
- 派遣标杆店长支援
- 提升首次修复率
- 优化周末排班
分析师的价值不在于做了多少分析,而在于带来了多少改变。
下一节(Day 38-7),我们将学习如何把这个分析流程自动化,实现一键生成周报。
准备好了吗?让我们继续! ?