1、线上总体优惠券弃用率为多少?
2、并找出优惠券弃用率最高的商家。
弃用率 = 被领券但未使用的优惠券张数 / 总的被领取优惠券张数
这题稍复杂,需要提前对【弃用率】做分析,所以先对数据源中的字段定义做分析,了解弃用率相关数据要如何获取?
数据详解
User_id:用户ID
Merchant_id:商户ID
Action:0 点击, 1购买,2领取优惠券
Coupon_id-优惠券ID:null表示无优惠券消费,此时Discount_rate和Date_received字段无意义
Discount_rate:优惠率:x in [0,1]代表折扣率;x:y表示满x减y。单位是元
Distance:user经常活动的地点离该merchant的最近门店距离是x*500米(如果是连锁店,则取最近的一家门店),xin[0,10];null表示无此信息,0表示低于500米,10表示大于5公里;
Date_received:领取优惠券日期
Date:消费日期:如果Date=null & Coupon_id != null,该记录表示领取优惠券但没有使用,即负样本;
如果Date!=null & Coupon_id = null,则表示普通消费日期;
如果Date!=null & Coupon_id != null,则表示用优惠券消费日期,即正样本
从数据源分析后了解到从【Date_received】字段中筛选出2016年6月期间数据,并从【Date】字段中筛选出符合领券要求的数据。
分析完毕后先做数据导入
import sqlalchemy as sac
import pandas as pd
engine=sac.create_engine('mysql+pymysql://user:password@host:3306/ali_sql')
df=pd.read_sql('select * from `ccf_online_stage1_train`',engine)
首先这里导入数据并没有做好,数据源此次有1千多万行,导入花费了很多时间。这里用了select * from 表的方式导入,其实可以先筛选下字段,不需要的字段去掉会比较合理。
df1=df[(df['Date']=='0000-00-00') & (df['Coupon_id']!='null')]
df1['Date_received']=pd.to_datetime(df1['Date_received']).dt.strftime('%Y-%m')
被领券但未使用数量=df1[df1['Date_received']=='2016-06']['Coupon_id'].count()
df2=df[df['Coupon_id']!='null']
df2['Date_received']=pd.to_datetime(df2['Date_received']).dt.strftime('%Y-%m')
总的被领取优惠券张数=df2[df2['Date_received']=='2016-06']['Coupon_id'].count()
print('弃用率: {:.2%}'.format(被领券但未使用数量/总的被领取优惠券张数))
接着开始梳理数据,先做条件筛选。
这次先筛选了【领券但未使用】,顺序上应该先处理时间数据。
但这里遇到个难题,如何处理'0000-00-00'的数据源?在SQL中其实代表的NaN值,但不理解为什么显示成这个样式。而导入到py中的数据都是object格式,如果用pd.to_datetime方法,无法转换这种样式的时间数据,导致无法筛选出2016年6月的数据。
所以就用笨办法,先筛选【Data】数据把‘0000-00-00’的值先过滤掉,过滤掉之后再处理时间数据类型。但这样做就比较麻烦,要多做一次筛选。如上代码,df1和df2都做了时间筛选处理。造成代码逻辑重复。
被领券但未使用的商家排名=df1[df1['Date_received']=='2016-06'].groupby('Merchant_id')[['Coupon_id']].count().sort_values(by='Coupon_id',ascending=False)
总的被领取优惠券数商家排名=df2[df2['Date_received']=='2016-06'].groupby('Merchant_id')[['Coupon_id']].count().sort_values(by='Coupon_id',ascending=False)
弃用率最高的商家=(被领券但未使用的商家排名/总的被领取优惠券数商家排名).sort_values(by='Coupon_id',ascending=False)[:1]
有了上面的数据预处理,商家的筛选结果就比较方便了。df.groupby方法把商家给筛选出来并计算排序
SQL代码-- 线上总体优惠券弃用率为多少? SELECt SUM(case when DATE='0000-00-00' AND Coupon_id IS NOT NULL then 1 ELSE 0 END)/ SUM(case when Coupon_id IS NOT NULL then 1 ELSE 0 END) AS rate FROM ccf_online_stage1_train WHERe Date_received BETWEEN '2016-06-01' AND '2016-06-30'
-- 并找出优惠券弃用率最高的商家。 SELECt Merchant_id,(SUM(case when DATE='0000-00-00' AND Coupon_id IS NOT NULL then 1 ELSE 0 END)/SUM(case when Coupon_id IS NOT NULL then 1 ELSE 0 END)) AS rate FROM ccf_online_stage1_train WHERe Date_received BETWEEN '2016-06-01' AND '2016-06-30' GROUP BY Merchant_id ORDER BY rate DESC LIMIT 1总结体会:
1、python在导入海量数据时,要先做筛选提高效率
2、python导入数据后要优先了解数据类型,便于数据预处理和清洗,为后面统计做准备
3、SQL在处理数据上要比python更加灵活,便捷。如果只是纯粹做数据处理应该用SQL,如果涉及后面的数据可视化,读写数据,预测等,那时才体现python优势。



