import numpy as np
import pandas as pd
import matplotlib.pyplot as plt
import seaborn as sns # 绘图模块,基于matplotlib可视化的python包,不能完全替代matplotlib,只是对mpl进行升级
plt.rcParams['font.sans-serif'] = ['SimHei'] # 用来正常显示中文标签
plt.rcParams['axes.unicode_minus'] = False # 用来正常显示符号
# parse_dates:将指定的列加载成日期的格式
offline = pd.read_csv('D:\Download\Microsoft Edge\数据分析实战项目资料\O2O\资料\ccf_offline_stage1_train.csv', parse_dates=['Date_received', 'Date'])
print(offline.info()) # 175+万条数据
print(offline.head(10)) # NaT:时间日期格式的空值
Discount_rate
列中的满减政策转换成折扣率200:20
替换成比例,计算折扣率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)
# map对这个变量数据里的每一个值都进行同一种操作
offline['Discount_rate'] = offline['Discount_rate'].map(discount_rate_opt)
print(offline['Discount_rate'].head())
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() #判断领券日期是否为空
print(np.all(nan1 == nan2))
nan3 = offline['Discount_rate'].isnull() #判断折扣率是否为空
print(np.all(nan1 == nan3))
分析:如果结果=true
,说明之前的猜测:Coupon_id
与Date_received
空值与非空值是一一对应的关系;如果结果=true
,说明之前的猜测:Coupon_id
与Discount_rate
空值与非空值是一一对应的关系
结果:
cpon_no_consume = offline[offline['Date'].isnull() & offline['Coupon_id'].notnull()]
no_cpon_no_consume = offline[offline['Date'].isnull() & offline['Coupon_id'].isnull()]
no_cpon_consume = offline[offline['Date'].notnull() & offline['Coupon_id'].isnull()]
cpon_consume = offline[offline['Date'].notnull() & offline['Coupon_id'].notnull()]
print('有优惠券未消费:{}'.format(len(cpon_no_consume)))
print('无优惠券未消费:{}'.format(len(no_cpon_no_consume)))
print('无优惠券有消费:{}'.format(len(no_cpon_consume)))
print('有优惠券有消费:{}'.format(len(cpon_consume)))
结果:
分析:用优惠券消费的有7w
,相比其他用户来说,占比较少
df
类型的数据,再将消费方式绘制成饼图consume_status_dict = {'cpon_no_consume': len(cpon_no_consume), 'no_cpon_consume': len(no_cpon_consume), 'cpon_consume': len(cpon_consume)}
consume_status = pd.Series(consume_status_dict)
print(consume_status)
fig, ax = plt.subplots(1, 1, figsize=(8, 10))
consume_status.plot.pie(ax=ax,
autopct='%1.1f%%', # 保留小数的占比情况
shadow=True, # 加阴影
explode=[0.02, 0.05, 0.02], # 各个参数间隔出来
textprops={'fontsize': 15, 'color': 'blue'}, # 字体字号颜色
wedgeprops={'linewidth': 1, 'edgecolor': 'black'}, # 边界线的宽度颜色
labels=['有优惠券未消费 \n ({})'.format(len(cpon_no_consume)),
'无优惠券有消费 \n ({})'.format(len(no_cpon_consume)),
'有优惠券有消费 \n ({})'.format(len(cpon_consume))
]
)
ax.set_ylabel('') # 取去掉None
ax.set_title('消费的占比情况') # 加标题
plt.legend(labels=['有优惠券未消费', '无优惠券有消费', '有优惠券有消费']) # 加图例
plt.show()
分析:有优惠券未消费占比55.7%
最大,说明大多数人拿完券之后,尚未使用;无优惠券有消费用户占比40%,说明很多人没有使用优惠券,可能优惠券的吸引力不大,客户没在意;可能新用户比较多优惠券有消费用户占比较小4.3%,说明我们的优惠券使用率不高,可以考虑是不是加大优惠券力度
Merchant_distance = cpon_consume.groupby('Merchant_id')['Distance'].mean()
print(Merchant_distance[Merchant_distance == 0])
# 距离值乘以500
结果:
分析:有4076
个商家,有1431
个商家的用券消费用户平均范围在500
米以内
erchant_distance_rate = cpon_consume.groupby('Merchant_id')['Discount_rate'].mean()
print(Merchant_distance_rate.sort_values())
Merchant_distance_rate.hist() # 绘制直方图,看折扣力度所在范围
print(Merchant_distance_rate.mean())
plt.show()
结果:
分析:大部分商家的折扣集中到0.8~1.0
之间,所有商家平均折扣的平均值:0.88,折扣力度不是很大
popular_merchant = cpon_consume.groupby('Merchant_id')['User_id'].apply(lambda x: len(x.unique())).sort_values(ascending=False)
popular_merchant500 = popular_merchant[popular_merchant > 500] # 找出持券消费人数>500的商家id
popular_merchant500.name = 'customer_count' # 指定列明为消费者数量(持券消费者)
print(len(popular_merchant500))
print(popular_merchant500)
结果:
分析:共有16
家店铺,持券消费人数在500
人以上;持券消费人数最多的商家是5341
,持券消费人数在2800
;排名最后的商家,持券消费人数是559
人;这批商家对优惠券的使用方法得当,消费者喜欢使用优惠券进行消费,可以适当借鉴这批商家的推广力度
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_distance_rate,on='Merchant_id', how='inner')
print(merchant_pop_dis_rate)
corr(correlation:相关系数)
,用来计算df数据中列与列的相关性(皮尔逊相关系数)取值范围[-1,1]
之间;1
:完全正相关,-1
:完全负相关;绝对值越大,相关性越大,反之成立;正相关:随着变量的增大而增大,反之同理;负相关:随着变量的增大而减小,反之同理;持券消费人数与距离和折扣率都呈现负相关,属于生活中的正常现象# 用热力图展示相关系数(data:相关系数,annot:显示相关系数的值,cmap:颜色范围,vmax:最大值,vmin:最小值)
sns.heatmap(data=merchant_pop_dis_rate.corr(), annot=True, cmap='RdPu', vmax=1, vmin=-1)
plt.show()
结果:
分析:由图可知,0<线性相关程度极弱<0.3<0.31<低度相关<0.5
;1.到店消费人数的多少与顾客到店铺之间的距离之间呈现负相关,相关系数0.31
,在0.3~0.5
之间,为低度相关;2.到店消费人数多少与优惠打折力度呈现负相关,相关系数0.2
,在0~0.3
之间,为相关系数极弱;综上所述,这些店家之所以火爆,应该是物美价廉导致,与距离和优惠力度相关性不大
Date_received
,使用日期Date
)用作图标的x
轴print('消费数量 %d' % offline['Date'].notnull().sum())
print('发送优惠券', offline['Date_received'].notnull().sum())
date_sort = offline[offline['Date'].notnull()]['Date'].sort_values().unique()
print(date_sort[:5])
date_received_sort = offline[offline['Date_received'].notnull()]['Date_received'].sort_values().unique()
print(date_sort[:5])
# 每天优惠券的使用量(即持券消费人数)
consume_num_everyday = cpon_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))
plt.bar(x=date_received_sort, height=coupon_sendout_everyday['count'], label='每天发券量')
plt.bar(x=date_received_sort, height=consume_num_everyday['count'], label='每天用券量')
# 对y轴进行对数缩放--量级相差比较多
plt.yscale('log')
plt.legend()
plt.show()
结果:
分析:16年2月份
为例,用券量级别在1000
,发券量在10万
左右,在100倍
左右,优惠券的使用率是非常低的
plt.figure(figsize=(18, 6))
plt.bar(x=date_received_sort, height=consume_num_everyday['count']/coupon_sendout_everyday['count'], label='百分比')
plt.legend()
plt.show()
结果:
分析:由图可知,优惠券使用率最高在16年3月底
,达到了30%
;使用率最低在16年1月底
,最低为3%
左右;整体来看,优惠券使用率波动较大。结合生活可以发现,优惠券投放与使用是否有三波小高峰?分别是元旦
、三八
、六一八
活动左右,而且优惠券的使用力度也与这个时间段相关。
55.7%
最大,说明大多数人拿完券之后,尚未使用;无优惠券有消费用户占比40%
,说明很多人没有使用优惠券,可能优惠券的吸引力不大,客户没在意;可能新用户比较多优惠券有消费用户占比较小4.3%
,说明我们的优惠券使用率不高,可以考虑是不是加大优惠券力度16年3月底
,达到了30%
;使用率最低在16年1月底
,最低为3%
左右;整体来看,优惠券使用率波动较大。优惠券投放与使用有三波小高峰,分别是元旦
、三八
、六一八
活动左右,而且优惠券的使用力度也与这个时间段相关。