import numpy as np
import pandas as pd
from matplotlib import pyplot as plt
(资料图)
import seaborn as sns # 绘图模块,基于matplotlib的可视化python包,不能完全替代matplotlib,只是对matplotlib进行升级
plt.rcParams['font.sans-serif'] = ['SimHei'] # 用来正常显示中文标签
plt.rcParams['axes.unicode_minus'] = False # 用来正常显示负号
"""
1.加载数据
parse_dates:将指定的列加载成日期的格式
"""
offline = pd.read_csv('ccf_offline_stage1_train.csv', parse_dates=['Date_received', 'Date'])
"""
2.数据的规整
判断每一列当中有多少个空值
offline.isnull().sum()
2.1 把“Discount_rate”列中的满减政策转换成折扣率
offline['Discount_rate'] = offline['Discount_rate'].fillna('null')
def discount_rate_opt(s): # s代表每一个元素
if ':' in s:
split = s.split(':')
discount_rate = (int(split[0]) - int(split[1]))/int(split[0])
return round(discount_rate, 2) # 折扣率保留两位小数
elif s == 'null':
return np.NaN
else:
return float(s)
offline['Discount_rate'] = offline['Discount_rate'].map(discount_rate_opt)
2.2 Coupon_id字段:null代表无优惠券,此时Discount_rate与Date_received字段无意义。检查Coupon_id与Discount_rate和Date_received判断空值和非空值是否一一对应
# np.all():判断一个可迭代数据中是否都为True,如果是返回True,否则返回False
nan1 = offline['Coupon_id'].isnull() # 判断优惠券是否为空
nan2 = offline['Date_received'].isnull() # 判断领券日期是否为空
nan3 = offline['Discount_rate'].isnull()
np.all(nan1 == nan2) # 如果结果为True,说明Coupon_id与Date_received空值与非空值是一一对应的关系
np.all(nan1 == nan3) # 如果结果为True,说明Coupon_id与Discount_rate空值与非空值是一一对应的关系
2.3 消费情况判断
如果Date == null & Coupon_id != null,有券未消费(coupon_no_consume)
如果Date == null & Coupon_id == null,无券未消费(no_coupon_no_consume)
如果Date != null & Coupon_id == null,无券消费(no_coupon_consume)
如果Date != null & Coupon_id != null,有券消费(coupon_consume)
"""
coupon_no_consume = offline[(offline['Date'].isnull() & offline['Coupon_id'].notnull())]
no_coupon_no_consume = offline[(offline['Date'].isnull() & offline['Coupon_id'].isnull())]
no_coupon_consume = offline[(offline['Date'].notnull() & offline['Coupon_id'].isnull())]
coupon_consume = offline[(offline['Date'].notnull() & offline['Coupon_id'].notnull())]
"""
print('有券未消费:{}'.format(len(coupon_no_consume)))
print('无券未消费:{}'.format(len(no_coupon_no_consume))) # 无意义,不需分析
print('无券消费:{}'.format(len(no_coupon_consume)))
print('有券消费:{}'.format(len(coupon_consume)))
# 用优惠券消费的有7万,相比其他用户来说,占比较少
3.数据分析
# 绘制饼图占比
consume_status_dict = {'coupon_no_consume': len(coupon_no_consume),
'no_coupon_consume': len(no_coupon_consume),
'coupon_consume': len(coupon_consume)}
consume_status = pd.Series(consume_status_dict)
# 消费方式构成的饼图(figure:看作是一张画布,axes:代表画布内的多个坐标系)
fig, ax = plt.subplots(1, 1, figsize=(8, 10), dpi=240)
consume_status.plot.pie(ax=ax,
autopct='%1.1f%%',
shadow=True,
explode=[0.02, 0.05, 0.2],
textprops={'fontsize': 15, 'color': 'blue'},
wedgeprops={'linewidth': 1, 'edgecolor': 'black'},
labels=['有券未消费 \n ({})'.format(len(coupon_no_consume)),
'无券消费 \n ({})'.format(len(no_coupon_consume)),
'有券消费 \n ({})'.format(len(coupon_consume)),
]
)
ax.set_ylabel('') # 去除ylabel
ax.set_title('消费占比情况')
plt.legend(labels=['有券未消费', '无券消费', '有券消费'])
# 有券未消费占比55.7%最大,说明大多数人拿完券之后,尚未使用;无券消费用户占比40%,说明很多人没有使用优惠券,可能优惠券的吸引力不大,客户没在意或者新用户比较多;用券消费用户比较小,占4.3%,说明优惠券使用率不高,可以考虑是不是加大优惠券力度......
3.1在有券消费人群中,分析距离和优惠折扣
# 各商家对应的顾客到点平均距离
Merchant_distance = coupon_consume.groupby('Merchant_id')['Distance'].mean()
print(Merchant_distance[Merchant_distance == 0])
# 有4076个商家,有1431个商家的用券消费用户平均范围在500米以内
# 各商家对应的顾客到点消费平均折扣力度
Merchant_discount_rate = coupon_consume.groupby('Merchant_id')['Discount_rate'].mean()
Merchant_discount_rate.sort_values()
Merchant_discount_rate.hist()
print(Merchant_discount_rate.mean())
# 所有商家平均折扣的平均值:0.88
3.2 持券到店消费人数最多的商家
# 对商家进行分组,取出用户id,对用户id进行去重统计数量
popular_merchant = coupon_consume.groupby('Merchant_id')['User_id'].apply(lambda x: len(x.unique())).sort_values(ascending=False)
# 找出持券消费人数>500的商家id
popular_merchant500 = popular_merchant[popular_merchant > 500]
# 共有16家店铺,持券消费人数在500人以上,持券消费人数最多商家是5341,持券消费人数在2800,排名最后的商家,持券消费人数为559人,这批商家对优惠券的使用方法得当,消费者喜欢用消费券进行消费,可以适当借鉴这批商家的推广力度
3.3 持券消费人数在500人以上的商家,连接顾客到店平均距离和平均折扣力度
merchant_pop_dis = pd.merge(left=popular_merchant500, right=Merchant_distance, on='Merchant_id', how='inner')
merchant_pop_dis_rate = pd.merge(left=merchant_pop_dis, right=Merchant_discount_rate, on='Merchant_id', how='inner')
3.4计算到点消费人数与平均距离和折扣力度的相关系数
corr(correlation:相关系数),用来计算df数据中列与列的相关性(皮尔逊相关系数),取值范围[-1,1]之间
1:完全正相关,-1:完全负相关;绝对值越大,相关性越大,反之同理
正相关:随着变量的增大,而增大,反之同理;负相关:随着变量的增大,而减小,反之同理
merchant_pop_dis_rate.corr()
# 持券消费人数,与距离和折扣率都呈现出负相关,属于生活中的正常现象
# 用热力图展示相关系数(data:相关系数,annot:显示相关系数,cmap:颜色范围,vmax:最大值,vmin:最小值)
sns.heatmap(data=merchant_pop_dis_rate.corr(),annot=True, cmap='Accent', vmax=1, vmin=-1)
由图可知:
1.到点消费人数的多少与顾客到店铺的距离之间呈现负相关,相关系数0.31,在0.3~0.5之间,为低度相关
2.到店消费人数的多少与优惠打折力度呈现负相关,相关系数0.2,在0~0.3之间,为相关程度极弱
综上所述,这些店家之所以火爆,应该是物美价廉导致,与距离和优惠力度相关性不大
4.1 分析每天中优惠券的总体发放量与使用量情况
业务分析:日期(优惠券的发放日期Date_received,使用日期date)用作图表的x轴
需要统计每天优惠券发放数量和使用数量
"""
offline['Date'].notnull().sum() # 77.7万消费数据
offline['Date_received'].notnull().sum() # 已经发送出105万优惠券
# 取出存在消费日期的记录,进行升序,再去重
date_sort = offline[offline['Date'].notnull()]['Date'].sort_values().unique()
# 取出存在领券日期的记录,进行升序,再去重
date_receive_sort = offline[offline['Date_received'].notnull()]['Date_received'].sort_values().unique()
# 每天优惠券的使用量(即持券消费人群)
consume_num_everyday = coupon_consume[['User_id', 'Date_received']]
consume_num_everyday = consume_num_everyday.groupby('Date_received').count()
consume_num_everyday = consume_num_everyday.rename(columns={'User_id': 'count'})
# 每天发放的优惠券数量(取出所有领券日期!=null的数据,再进行按天分组,计数就可以)
coupon_sendout_everyday = offline[offline['Date_received'].notnull()][['Date_received', 'User_id']]
coupon_sendout_everyday = coupon_sendout_everyday.groupby('Date_received').count()
coupon_sendout_everyday = coupon_sendout_everyday.rename(columns={'User_id': 'count'})
# 绘制每天发券量和每天用券量
plt.figure(figsize=(18, 6), dpi=400)
plt.bar(x=date_receive_sort, height=coupon_sendout_everyday['count'], label='每天发券量')
plt.bar(x=date_receive_sort, height=consume_num_everyday['count'], label='每天用券量')
plt.yscale('log') # 对y轴进行对数缩放
plt.legend()
# 16年2月为例,用券量级别在1000,发券量在10万左右,在100倍左右,优惠券的使用率还是非常低的
# 计算每天的优惠券与发券量占比
plt.figure(figsize=(18,6), dpi=400)
plt.bar(x=date_receive_sort, height=consume_num_everyday['count']/coupon_sendout_everyday['count'], label='百分比')
plt.legend()
# 由图可知,优惠券使用率最高在16年3月底,达到了30%,使用率最低在16年1月底,最低为3%左右。整体来看,优惠券使用率波动较大