此处为网站链接地址:https://tianchi.aliyun.com/competition/entrance/231593/information里面有竞赛数据和要求标准以及每张表的字段
在这里是站在了巨人的肩膀上进行的, O(∩_∩)O哈哈哈~, 不过还是考验对知识的理解和对问题的分析能力, 感谢竞赛中各路大佬的经验分享.
所有的模型训练, 分析表中的特征是首要任务, 不过这三张表中的特征还是比较少的, 所以比较好分析, 但是他们之间的特征关系就比较多了
主要的用户特征处理
def is_firstlastone(x):
if x == 0:
return 1
elif x > 0:
return 0
else:
return -1 # 表明这个优惠券只接受了一次
def get_day_gap_before(s):
date_received, dates = s.split('-')
dates = dates.split(':')
gaps = []
for d in dates:
# 将时间差转化为天数
this_gap = (dt.date(int(date_received[0:4]), int(date_received[4:6]), int(
date_received[6:8]))-dt.date(int(d[0:4]), int(d[4:6]), int(d[6:8]))).days
if this_gap > 0:
gaps.append(this_gap)
if len(gaps) == 0:
return -1
else:
return min(gaps)
def get_day_gap_after(s):
date_received, dates = s.split('-')
dates = dates.split(':')
gaps = []
for d in dates:
this_gap = (dt.datetime(int(d[0:4]), int(d[4:6]), int(d[6:8]))-dt.datetime(
int(date_received[0:4]), int(date_received[4:6]), int(date_received[6:8]))).days
if this_gap > 0:
gaps.append(this_gap)
if len(gaps) == 0:
return -1
else:
return min(gaps)
def GetOtherFeature(dataset):
# 对于测试集,提取用户的Id
dataset3 = dataset
t = dataset3[['user_id']]
# 相当于给原有数据加上一列,这个月用户收取的所有优惠券数目,并初始化为1
t['this_month_user_receive_all_coupon_count'] = 1
# 将t按照用户id进行分组,然后统计所有用户收取的优惠券数目,并初始化一个索引值
t = t.groupby('user_id').agg('sum').reset_index()
# 提取数据集的优惠券Id和用户Id
t1 = dataset3[['user_id', 'coupon_id']]
# 提取这个月用户收到的相同的优惠券的数量
t1['this_month_user_receive_same_coupn_count'] = 1
t1 = t1.groupby(['user_id', 'coupon_id']).agg('sum').reset_index()
# 提取数据集的用户id,优惠券id以及优惠券接收的时间
t2 = dataset3[['user_id', 'coupon_id', 'date_received']]
# 将数据转换为str类型
t2.date_received = t2.date_received.astype('str')
# 如果出现相同的用户接收相同的优惠券在接收时间上用‘:’连接上第n次接受优惠券的时间
t2 = t2.groupby(['user_id', 'coupon_id'])['date_received'].agg(
lambda x: ':'.join(x)).reset_index()
# 将接收时间的一组按着':'分开,这样就可以计算接受了优惠券的数量,apply是合并
t2['receive_number'] = t2.date_received.apply(lambda s: len(s.split(':')))
t2 = t2[t2.receive_number > 1]
# 最大接受的日期
t2['max_date_received'] = t2.date_received.apply(
lambda s: max([int(d) for d in s.split(':')]))
# 最小的接收日期
t2['min_date_received'] = t2.date_received.apply(
lambda s: min([int(d) for d in s.split(':')]))
t2 = t2[['user_id', 'coupon_id', 'max_date_received', 'min_date_received']]
t3 = dataset3[['user_id', 'coupon_id', 'date_received']]
# 将两表融合只保留左表数据,这样得到的表,相当于保留了最近接收时间和最远接受时间
t3 = pd.merge(t3, t2, on=['user_id', 'coupon_id'], how='left')
# 这个优惠券最近接受时间
t3['this_month_user_receive_same_coupon_lastone'] = t3.max_date_received - \
t3.date_received.astype(int)
# 这个优惠券最远接受时间
t3['this_month_user_receive_same_coupon_firstone'] = t3.date_received.astype(
int)-t3.min_date_received
t3.this_month_user_receive_same_coupon_lastone = t3.this_month_user_receive_same_coupon_lastone.apply(
is_firstlastone)
t3.this_month_user_receive_same_coupon_firstone = t3.this_month_user_receive_same_coupon_firstone.apply(
is_firstlastone)
t3 = t3[['user_id', 'coupon_id', 'date_received', 'this_month_user_receive_same_coupon_lastone',
'this_month_user_receive_same_coupon_firstone']]
# 将表格中接收优惠券日期中为最近和最远的日期时置为1其余为0,若只接受了一次优惠券为-1
# 提取第四个特征,一个用户所接收到的所有优惠券的数量
t4 = dataset3[['user_id', 'date_received']]
t4['this_day_receive_all_coupon_count'] = 1
t4 = t4.groupby(['user_id', 'date_received']).agg('sum').reset_index()
# 提取第五个特征,一个用户不同时间所接收到不同优惠券的数量
t5 = dataset3[['user_id', 'coupon_id', 'date_received']]
t5['this_day_user_receive_same_coupon_count'] = 1
t5 = t5.groupby(['user_id', 'coupon_id', 'date_received']
).agg('sum').reset_index()
# 一个用户不同优惠券 的接受时间
t6 = dataset3[['user_id', 'coupon_id', 'date_received']]
t6.date_received = t6.date_received.astype('str')
t6 = t6.groupby(['user_id', 'coupon_id'])['date_received'].agg(
lambda x: ':'.join(x)).reset_index()
# 重命名inplace代表深拷贝
t6.rename(columns={'date_received': 'dates'}, inplace=True)
t7 = dataset3[['user_id', 'coupon_id', 'date_received']]
# 将t6和t7融合
t7 = pd.merge(t7, t6, on=['user_id', 'coupon_id'], how='left')
# 注意这里所有的时间格式都已经是'str'格式
t7['date_received_date'] = t7.date_received.astype('str')+'-'+t7.dates
# print(t7)
t7['day_gap_before'] = t7.date_received_date.apply(get_day_gap_before)
t7['day_gap_after'] = t7.date_received_date.apply(get_day_gap_after)
t7 = t7[['user_id', 'coupon_id', 'date_received',
'day_gap_before', 'day_gap_after']]
# 将所有特征融合在一张表中
other_feature3 = pd.merge(t1, t, on='user_id')
other_feature3 = pd.merge(other_feature3, t3, on=['user_id', 'coupon_id'])
other_feature3 = pd.merge(other_feature3, t4, on=['user_id', 'date_received'])
other_feature3 = pd.merge(other_feature3, t5, on=[
'user_id', 'coupon_id', 'date_received'])
other_feature3 = pd.merge(other_feature3, t7, on=[
'user_id', 'coupon_id', 'date_received'])
return other_feature3
提取优惠券的相关特征
def calc_discount_rate(s):
s = str(s)
s = s.split(':')
if len(s) == 1:
return float(s[0])
else:
return 1.0-float(s[1])/float(s[0])
def get_discount_man(s):
s = str(s)
s = s.split(':')
if len(s)==1:
return 'null'
else:
return int(s[0])
def get_discount_jian(s):
s = str(s)
s = s.split(':')
if len(s) == 1:
return 'null'
else:
return int(s[1])
def is_man_jian(s):
s = str(s)
s = s.split(':')
if len(s)==1:
return 0
else:
return 1 def calc_discount_rate(s):
s = str(s)
s = s.split(':')
if len(s) == 1:
return float(s[0])
else:
return 1.0-float(s[1])/float(s[0])
def get_discount_man(s):
s = str(s)
s = s.split(':')
if len(s)==1:
return 'null'
else:
return int(s[0])
def get_discount_jian(s):
s = str(s)
s = s.split(':')
if len(s) == 1:
return 'null'
else:
return int(s[1])
def is_man_jian(s):
s = str(s)
s = s.split(':')
if len(s)==1:
return 0
else:
return 1
def GetCouponFeature(dataset, feature):
# 对于数据集
# 将时间转化为第几周
# 显示时间是第几周
# tt是获取到的特征中消费的最大时间
dataset3 = dataset
tt = feature[feature.date != 'null'].date.unique().max()
dataset3['day_of_week'] = dataset3.date_received.astype('str').apply(
lambda x: date(int(x[0:4]), int(x[4:6]), int(x[6:8])).weekday()+1)
# 显示时间是几月
dataset3['day_of_month'] = dataset3.date_received.astype(
'str').apply(lambda x: int(x[6:8]))
# 显示时期和截止日之间的天数
dataset3['days_distance'] = dataset3.date_received.astype('str').apply(
lambda x: (date(int(x[0:4]), int(x[4:6]), int(x[6:8]))-date(int(tt[0:4]), int(tt[4:6]), int(tt[6:8]))).days)
# 显示满了多少钱后开始减
dataset3['discount_man'] = dataset3.discount_rate.apply(get_discount_man)
# 显示满减的减少的钱
dataset3['discount_jian'] = dataset3.discount_rate.apply(get_discount_jian)
# 返回优惠券是否是满减券
dataset3['is_man_jian'] = dataset3.discount_rate.apply(is_man_jian)
# 显示打折力度
dataset3['discount_rate'] = dataset3.discount_rate.apply(
calc_discount_rate)
d = dataset3[['coupon_id']]
d['coupon_count'] = 1
# 显示每一种优惠券的数量
d = d.groupby('coupon_id').agg('sum').reset_index()
dataset3 = pd.merge(dataset3, d, on='coupon_id', how='left')
return dataset3
感谢大神的分享地址: https://github.com/wepe/O2O-Coupon-Usage-Forecast
后续内容, 请见下次分享~~~