天池- IJCAI-18 阿里妈妈搜索广告转化预测新手入门经历(上:数据预处理、特征工程)

第一次正式参加数据挖掘类的比赛,投入了三个星期。结果没有进入复赛,但是学到了许多经验。感谢技术圈和github的大佬们提供的baseline,让我少走了很多弯路。

第一次写博客,其一为了防止以后忘记,其二如果 能帮到萌新们也是很开心啦。

思路:全文按照数据预处理、特征工程和模型融合讲解,并附有代码。

数据预处理

1、导入库和读取数据

导入库:
import pandas as pd
import numpy as np
import lightgbm as lgb
from sklearn.model_selection import train_test_split
from sklearn.metrics import log_loss
from sklearn import preprocessing
import warnings
from sklearn.grid_search import GridSearchCV 
warnings.filterwarnings("ignore")
from sklearn.model_selection import StratifiedKFold
import time
from itertools import product
import copy
import itertools
import seaborn as sns
读取测试集和训练集:
train是训练数据,test是需要预测的测试集(这里用的是B榜的test_b)。

分析数据时会发现训练集中有少量样本'instance_id'字段重复,但在比赛B榜的test_b中也有重复样本,所以不进行去重。

train = pd.read_csv(r'C:\Users\Lee\Desktop\round\origin_data\round1_ijcai_18_train_20180301.txt', sep="\s+")
test = pd.read_csv(r'C:\Users\Lee\Desktop\round\origin_data\round1_ijcai_18_test_b_20180418.txt', sep="\s+")
data = pd.concat([train, test])
#data = data.drop_duplicates(subset='instance_id')
data = data.reset_index(drop = True)

2、数据预处理

文本类特征处理
数据有3个文本类型特征item_category_list、item_property_list和predict_category_property,使用split分割。

item_category_list特征有3个字段,第一个字段所有数据一样,所以取range(1,3)

item_property_list特征有100个字段,各字段之间无从属关系,由于后面字段缺失值太多,所以取range(19)

predict_category_property特征有14个字段,有从属关系,缺失值太多取range(5)

并使用LabelEncoding进行编码。

    lbl = preprocessing.LabelEncoder()
    for i in range(1, 3):
        data['item_category_list' + str(i)] = lbl.fit_transform(data['item_category_list'].map(
            lambda x: str(str(x).split(';')[i]) if len(str(x).split(';')) > i else ''))  # item_category_list的第0列全部都一样
    for i in range(19):
        data['item_property_list' + str(i)] = lbl.fit_transform(data['item_property_list'].map(lambda x: str(str(x).split(';')[i]) if len(str(x).split(';')) > i else '')) 
    for i in range(7):
                data['predict_category_property' + str(i)] = lbl.fit_transform(data['predict_category_property'].map(
                lambda x: str(str(x).split(';')[i]) if len(str(x).split(';')) > i else ''))
时间戳处理

数据中的时间是以时间戳形式存在,进行如下处理提取日期和时间

    data['realtime'] = data['context_timestamp'].apply(lambda x:time.strftime('%Y-%m-%d %H:%M:%S',time.localtime(x)))
    data['realtime'] = pd.to_datetime(data['realtime'])
    data['day'] = data['realtime'].dt.day
    data['hour'] = data['realtime'].dt.hour

特征工程

长度特征

每条样本的3个文本特征的长度不一样,其中也许包含了一些信息。例如商品的属性列表很详细,可能是比较精细的产品,例如电脑和显卡两种商品,电脑参数包括CPU/显卡/内存等多项信息,显然比显卡复杂。

因此长度特征可以描述商品的种类。

    data['len_item_category'] = data['item_category_list'].map(lambda x: len(str(x).split(';')))
    data['len_item_property'] = data['item_property_list'].map(lambda x: len(str(x).split(';')))
    data['len_predict_category_property'] = data['predict_category_property'].map(lambda x: len(str(x).split(';')))
    
基于商店质量的shop分段特征

shop中有4个连续型特征:shop_score_description、shop_score_delivery、

shop_score_service、shop_review_positive_rate

以shop_score_description为例,一条样本的取值是4.9632654,我们期望得知这个取值在总体样本中得分是处于什么样的一个水平。就需要进行分段,代码中0,1,2代表较差、一般、优秀3个等级。

分段还有一个好处就是可以和其他特征进行组合,后面会提到。

    data['shop_score_description0'] = data['    '].apply(lambda x: 2 if x > 0.984 else x)
    data['shop_score_description0'] = data['shop_score_description0'].apply(lambda x: 1 if 0.984 >= x > 0.97 else x)
    data['shop_score_description0'] = data['shop_score_description0'].apply(lambda x: 0 if  x <= 0.97 else x)
    
    data['shop_score_delivery0'] = data['shop_score_delivery'].apply(lambda x: 2 if x > 0.979 else x)
    data['shop_score_delivery0'] = data['shop_score_delivery0'].apply(lambda x: 1 if 0.979 >= x > 0.966 else x)
    data['shop_score_delivery0'] = data['shop_score_delivery0'].apply(lambda x: 0 if  x <= 0.966 else x)
    
    data['shop_score_service0'] = data['shop_score_service'].apply(lambda x: 2 if x > 0.979 else x)
    data['shop_score_service0'] = data['shop_score_service0'].apply(lambda x: 1 if 0.979 >= x > 0.967 else x)
    data['shop_score_service0'] = data['shop_score_service0'].apply(lambda x: 0 if  x <= 0.967 else x)
    
    data['shop_review_positive_rate0'] = data['shop_review_positive_rate'].apply(lambda x: 2 if x == 1 else x)
    data['shop_review_positive_rate0'] = data['shop_review_positive_rate0'].apply(lambda x: 1 if 1 > x > 0.98 else x)
    data['shop_review_positive_rate0'] = data['shop_review_positive_rate0'].apply(lambda x: 0 if  x <= 0.98 else x)
    

基于历史点击率的分段特征

以user_age_level为例,我们观察该特征和是否点击is_trade的图:

sns.pointplot(x='user_age_level', y='is_trade', data=data)

可以看到点击率随着用户年龄上升而上升。这说明年龄在1005的用户最容易点击广告,可以脑补一下:1005应该对应的年龄是40-50岁之间,这个阶段的用户有经济实力,工作比较稳定(上班比较悠闲),有较强的点击广告的动机。

user_age_level这个特征区分度很高,可以不用做分段。



再看店铺评价数量等级shop_review_num_level和is_trade的关系:


就不如用户年龄那样呈明显的线性关系了,这个时候就可以进行分段。

def review_num(x):
    if (x==1)|(x==22)|(x==25):
        return 1
    elif ((x>=3)&(x<=5))|(x==23):
        return 2
    else:
        return 3    
data['shop_review_num_level'] = data['shop_review_num_level'].apply(review_num)

现在我们可以看看分段后的效果

sns.pointplot(x='shop_review_num_level', y='is_trade', data=data)

可以发现这一特征对'is_trade'的区分度提高了。即shop_review_num_level为3的点击概率越大,这一信息相比分段前能够更好地帮助模型做判断。

但是要注意这种特征本质上是带有穿越性的,我统计的是整个数据集中shop_review_num_level的点击率。data包括7月18-25用户是否点击广告的所有样本,而在判断单条7月20日的样本是否点击广告的时候,是无法知道20日后面的用户的行为的。

所以说,这种带有穿越性的特征十分容易导致过拟合,相当于拿着试卷答案在做试卷。在后面的统计特征中更要注意这一点。

基于点击率的特征

如果我们能够知道某件商品以前的点击率。极端点说,如果有一个特征item_brand_id中为'豪牛'的牛奶品牌的广告,以前推送了100条广告,没有一个用户点击,点击率就为0。而另一个为'大草原'的牛奶品牌推送了50条广告,有25名用户点击,点击率为0.5。

那么在后面的预测中可以推断'豪牛'的广告大概率不会被点击,'大草原'的广告有50%的几率会被点击。并且两个品牌的点击率的可信度也是不一致的,'豪牛'样本量大,可信度自然会高。

所以应该统计两个信息:该广告的历史推送条数、该广告的历史点击率

def get_cnt(data,col_name):
      '''  Descr:输入:带有日期特征的数据集data,特征名称col_name
            输出:带有两个新特征的data:
                    该特征的历史推送次数:col_name+'_cnt'
                   该特征的历史点击率:col_name+'_cntrate11'
                   '''
    user_cnt = data.groupby(by=[col_name,'day'])['is_trade'].agg({col_name+'_cnt': 'count'})
    user_cnt = user_cnt.unstack()
    user_cnt.fillna(0,inplace=True)
    user_cnt = user_cnt.reindex_axis(sorted(user_cnt.columns), axis=1)
    user_cnt = user_cnt.cumsum(axis=1)
    user_cnt = user_cnt.stack()
    user_cnt = user_cnt.reset_index()
    user_cnt['day'] = user_cnt['day'].map(lambda x: x+1)
   
    
    user_cnt1 = data.groupby(by=[col_name,'day','is_trade']).agg( 'size')
    user_cnt1 = user_cnt1.unstack(level=['is_trade','day'])
    user_cnt1 = user_cnt1[:][1]
    user_cnt1.fillna(0,inplace=True)
    day_list = user_cnt1.columns.tolist()
    user_cnt1 = user_cnt1.reindex_axis(sorted(day_list), axis=1)
    user_cnt1 = user_cnt1.cumsum(axis=1)
    user_cnt1 = user_cnt1.stack()
    user_cnt1 = user_cnt1.reset_index()
    user_cnt1.columns = [col_name,'day',col_name+'_cntrate11']
    user_cnt1['day'] = user_cnt1['day'].map(lambda x: x+1)
    
    data = pd.merge(data,user_cnt,on=[col_name,'day'],how='left')
    data = pd.merge(data,user_cnt1,on=[col_name,'day'],how='left')
    data[col_name+'_cntrate11'] = data[col_name+'_cntrate11']/data[col_name+'_cnt']
#    del data[col_name+'_cnt']
    
    return data
def get_all_cnt(data):
    '''   
    Descr:输入:数据data,统计函数get_cnt(data,col_name)
                需要统计的特征列表(此处函数内部已定义)
            输出:包含每个特征的历史点击率、历史推送次数的data
    
    '''
   item_name = ['item_sales_level', 'item_price_level', 'item_collected_level','item_pv_level','item_brand_id','item_city_id']
   user_name = ['user_gender_id','user_age_level','user_occupation_id','user_star_level']
   shop_name = ['shop_review_num_level','shop_star_level',]
   id_name = ['user_id','item_id','shop_id','context_page_id']
  
   all_name = item_name+id_name+user_name+shop_name+['hour']
  for col_name in all_name:
        print('------>正在统计单一特征:'+col_name)
        data = get_cnt(data,col_name)
     return data

调用:

data = get_all_cnt(data)

基于组合特征的点击率特征

该特征统计的是两个特征组合起来的历史点击率和推送次数。

例如:'item_brand_id'为'大草原'品牌和‘user_age_level’为'1005'时的点击率为0.01,

'item_brand_id'为'大草原'品牌和‘user_age_level’为'1007'时的点击率为0.8

包含了'大草原'品牌可能主打老年奶粉,许多老年人(user_age_level’=1007)的用户会点击这条广告

def get_cross_cnt2(data,col_name,base_name):
    '''  
    Descr:输入:数据data,需要组合的特征名col_name,base_name,无先后顺序
        输出:含有该组合特征的历史推送次数col_name+'_'+base_name+'_cnt'
            历史点击率col_name+'_'+base_name+'_cross_cntrate11'
      example:
        col_name = 'item_brand_id'
        base_name = 'item_id'
    '''

    
    cnt = data.groupby(by = [col_name,base_name,'day'])['is_trade'].agg({col_name+'_'+base_name+'_cnt':'count'})
    cnt = cnt.unstack()
    cnt.fillna(0,inplace=True)
    cnt = cnt.reindex_axis(sorted(cnt.columns),axis = 1)
    cnt = cnt.cumsum(axis = 1)
    cnt = cnt.stack()
    cnt = cnt.reset_index()
    cnt['day'] = cnt['day'].map(lambda x : x+1)
    
    cnt1 = data.groupby(by=[col_name,base_name,'day','is_trade']).agg('size')
    cnt1 = cnt1.unstack(level=['is_trade','day'])
    cnt1 = cnt1[:][1]
    cnt1.fillna(0,inplace=True)
    cnt1 = cnt1.reindex_axis(sorted(cnt1.columns.tolist()),axis = 1)
    cnt1 = cnt1.cumsum(axis = 1)
    cnt1 = cnt1.stack()
    cnt1 = cnt1.reset_index()
    cnt1.columns = [col_name,base_name,'day',col_name+'_'+base_name+'_cross_cntrate11']
    cnt1['day'] = cnt1['day'].map(lambda x:x+1)

    data = pd.merge(data,cnt,on=[col_name,base_name,'day'],how='left')
    data = pd.merge(data,cnt1,on=[col_name,base_name,'day'],how='left')
    data[col_name+'_'+base_name+'_cross_cntrate11'] = data[col_name+'_'+base_name+'_cross_cntrate11']/data[col_name+'_'+base_name+'_cnt']
#    del data[col_name+'_'+base_name+'_cnt']
    return data
这里有两个小问题
(1)如何组合特征

特征可以分为三大类user,shop,item

那么组合特征有两种方式:

1、按照大类的属性进行组合(大类属性内部不进行组合,例如不会出现user_age_level_user_gender_level这样的组合特征):

user_xxx_item_xxx

user_xxx_shop_xxx

item_xxx_shop_xxx

2、不按照大类属性,所有类两两组合:

比第一种会多出:

item_xxx_item_xxx

user_xxx_user_xxx

shop_xxx_shop_xxx

在使用lgb输出重要度时可以发现第二种组合更优秀。


def get_all_cross_cnt(data):
'''   
    Descr:输入:数据data,统计函数get_cnt(data,col_name,base_name)
                需要统计的特征列表(此处函数内部已定义)
            输出:包含两两组合特征的历史点击率、历史推送次数的data
'''
    item_name_level = [
            'item_id',
            'context_page_id',
            'item_sales_level', 'item_price_level', 'item_collected_level','item_pv_level','item_brand_id','item_city_id']


    user_name = [
            'user_id',
            'user_gender_id','user_age_level','user_occupation_id','user_star_level'
                 ]


    shop_name = [
            'shop_id',
            'shop_review_num_level','shop_star_level',
#            'shop_review_positive_rate0','shop_score_service0','shop_score_delivery0','shop_score_description0',
                        'normal_shop'                     
                     ]


    
  
    all_name = item_name_level+user_name+shop_name+['hour'
#                                                    ,'hour1','hour2'
                                                   ]
    count = 0
    for i in itertools.permutations(all_name,2):
        data = get_cross_cnt2(data,i[0],i[1])
        count = count+1
        print count


    return data

    
  
    all_name = item_name_level+user_name+shop_name+['hour'
#                                                    ,'hour1','hour2'
                                                   ]
    count = 0
    for i in itertools.permutations(all_name,2):
        data = get_cross_cnt2(data,i[0],i[1])
        count = count+1
        print count

    return data
(2)统计组合特征时还可以统计的一些信息

对于两个特征col和base,有如下6个单一统计特征:

[col]推送次数

[base]推送次数

[col_base]推送次数

[col_base]点击次数

[col]点击次数

[base]点击次数

前面统计了单一特征的历史点击率:

[col]点击次数  /  [col]推送次数

 [base]点击次数 / [base]推送次数

以及组合特征的历史点击率:

[col_base]点击次数 / [col_base]推送次数

实际上还可以统计的特征有:

[col_base]推送次数 / [col]推送次数

[col_base]推送次数 / [base]推送次数

[col_base]点击次数 / [col]点击次数

[col_base]点击次数 / [base]点击次数

前面两个从商家角度(广告推送者)出发,统计商家的市场占有率、推广程度,

后面两个从用户角度(是否点击)出发,统计用户对产品的喜爱程度。

例如col = 'item_brand_id' , base = 'item_city_id'

[col_base]推送次数 / [col]推送次数,以第一行的0.8为例,

在这里的意义就是:大草原在北京和上海都投放了广告,但是大草原主打北京,在北京投放了80%的广告。

[col_base]推送次数 / [base]推送次数,以第一行的0.66为例,

在北京一共投放了10条广告,其中大草原投放了66%的广告,而竞争对手豪牛投放了33%的广告。

同理,后面两个公式可以统计用户对大草原的点击率和豪牛的点击率

但是在实际应用中效果不好,所以没有统计。

def get_cross_cnt(data,col_name,base_name):
    '''
    Descr:输入数据data,输出5个统计信息:
            [col_base]点击次数 / [col_base]推送次数
            [col_base]推送次数 / [col]推送次数
            [col_base]推送次数 / [base]推送次数
            [col_base]点击次数 / [col]点击次数
            [col_base]点击次数 / [base]点击次数
    example:
    col_name = 'item_brand_id'
    base_name = 'item_id'
    '''
    cnt = data.groupby(by = [col_name,base_name,'day'])['is_trade'].agg({col_name+'_'+base_name+'_cnt':'count'})
    cnt = cnt.unstack()
    cnt.fillna(0,inplace=True)
    cnt = cnt.reindex_axis(sorted(cnt.columns),axis = 1)
    cnt = cnt.cumsum(axis = 1)
    cnt = cnt.stack()
    cnt = cnt.reset_index()
    cnt['day'] = cnt['day'].map(lambda x : x+1)
    
    cnt1 = data.groupby(by=[col_name,base_name,'day','is_trade']).agg('size')
    cnt1 = cnt1.unstack(level=['is_trade','day'])
    cnt1 = cnt1[:][1]
    cnt1.fillna(0,inplace=True)
    cnt1 = cnt1.reindex_axis(sorted(cnt1.columns.tolist()),axis = 1)
    cnt1 = cnt1.cumsum(axis = 1)
    cnt1 = cnt1.stack()
    cnt1 = cnt1.reset_index()
    cnt1.columns = [col_name,base_name,'day',col_name+'_'+base_name+'_cross_cntrate11']
    cnt1['day'] = cnt1['day'].map(lambda x:x+1)

    data = pd.merge(data,cnt,on=[col_name,base_name,'day'],how='left')
    data = pd.merge(data,cnt1,on=[col_name,base_name,'day'],how='left')
    
#    col_name的单特征量
    cnt_col = data.groupby(by = [col_name,'day'])['is_trade'].agg({col_name+'_cnt':'count'})
    cnt_col = cnt_col.unstack()
    cnt_col.fillna(0,inplace=True)
    cnt_col = cnt_col.reindex_axis(sorted(cnt_col.columns),axis = 1)
    cnt_col = cnt_col.cumsum(axis = 1)
    cnt_col = cnt_col.stack()
    cnt_col = cnt_col.reset_index()
    cnt_col['day'] = cnt_col['day'].map(lambda x : x+1)

    cnt_col1 = data.groupby(by=[col_name,'day','is_trade']).agg( 'size')
    cnt_col1 = cnt_col1.unstack(level=['is_trade','day'])
    cnt_col1 = cnt_col1[:][1]
    cnt_col1.fillna(0,inplace=True)
    cnt_col1 = cnt_col1.reindex_axis(sorted(cnt_col1.columns.tolist()), axis=1)
    cnt_col1 = cnt_col1.cumsum(axis=1)
    cnt_col1 = cnt_col1.stack()
    cnt_col1 = cnt_col1.reset_index()
    cnt_col1.columns = [col_name,'day',col_name+'_cntrate11']
    cnt_col1['day'] = cnt_col1['day'].map(lambda x: x+1)
    
    data = pd.merge(data,cnt_col,on=[col_name,'day'],how='left')
    data = pd.merge(data,cnt_col1,on=[col_name,'day'],how='left')
    
#    base_name的单特征量
    cnt_base = data.groupby(by = [base_name,'day'])['is_trade'].agg({base_name+'_cnt':'count'})
    cnt_base = cnt_base.unstack()
    cnt_base.fillna(0,inplace=True)
    cnt_base = cnt_base.reindex_axis(sorted(cnt_base.columns),axis = 1)
    cnt_base = cnt_base.cumsum(axis = 1)
    cnt_base = cnt_base.stack()
    cnt_base = cnt_base.reset_index()
    cnt_base['day'] = cnt_base['day'].map(lambda x : x+1)

    cnt_base1 = data.groupby(by=[base_name,'day','is_trade']).agg( 'size')
    cnt_base1 = cnt_base1.unstack(level=['is_trade','day'])
    cnt_base1 = cnt_base1[:][1]
    cnt_base1.fillna(0,inplace=True)
    cnt_base1 = cnt_base1.reindex_axis(sorted(cnt_base1.columns.tolist()), axis=1)
    cnt_base1 = cnt_base1.cumsum(axis=1)
    cnt_base1 = cnt_base1.stack()
    cnt_base1 = cnt_base1.reset_index()
    cnt_base1.columns = [base_name,'day',base_name+'_cntrate11']
    cnt_base1['day'] = cnt_base1['day'].map(lambda x: x+1)
    
    data = pd.merge(data,cnt_base,on=[base_name,'day'],how='left')
    data = pd.merge(data,cnt_base1,on=[base_name,'day'],how='left')
    
#    col_name+'_'+base_name+'_cross_cntrate11'
    data[col_name+'_'+base_name+'_cb'] = data[col_name+'_'+base_name+'_cross_cntrate11']/data[col_name+'_'+base_name+'_cnt']
    
    data[col_name+'_'+base_name+'_cb_c'] = data[col_name+'_'+base_name+'_cnt']/data[col_name+'_cnt']
    data[col_name+'_'+base_name+'_cb_b'] = data[col_name+'_'+base_name+'_cnt']/data[base_name+'_cnt']
    
    data[col_name+'_'+base_name+'_cb_c1'] = data[col_name+'_'+base_name+'_cross_cntrate11']/data[col_name+'_cntrate11']
    data[col_name+'_'+base_name+'_cb_b1'] = data[col_name+'_'+base_name+'_cross_cntrate11']/data[base_name+'_cntrate11']

    del data[col_name+'_'+base_name+'_cnt']
    del data[col_name+'_cnt']
    del data[base_name+'_cnt']
    del data[col_name+'_'+base_name+'_cross_cntrate11']
    del data[col_name+'_cntrate11']
    del data[base_name+'_cntrate11']
    return data
其他一些效果不太好的特征:

1、对离散型特征字符串化,再累加的组合特征

比如user_gender_id='1',user_age_level='2'

那么组合特征'12'就代表着中年('2')女性('1')的含义。

有一个问题是代码只对特征做简单的LabelEncoding处理,假设第一个特征取值为1-2000,第二个特征取值为1-100,那么'2213'实际上可能有多种字符串拼接方式:

'2'+'213'

'22'+'13'

'221'+'3'

都是这一特征,也许这就是效果不好的原因吧,下次比赛的时候再试试。

def zuhe(data):
    '''
    Desr:输入:数据data
    1、使用preprocessing.LabelEncoder()使特征在一个小区间内
    2、转换int行特征为str
    3、两两字符型特征累加
        输出:字符串组合特征
        example:
            item_brand_id:'2'
            item_city_id:'1'
            
            zuhe_feature:21
                
    '''
    print('3.zuhe')
    print('-------------------把缺失值-1替换为0----------------------')
#    for col in ['user_gender_id','user_age_level','user_occupation_id','user_star_level']:
#        data[col] = data[col].apply(lambda x: 0 if x == -1 else x)
    print('-----------声明item,shop,user,hour四个块中的特征名----------')
    
    item_category_list_name = ['item_category_list'+str(i) for i in range(1,3)]
    item_property_list_name = ['item_property_list'+str(i) for i in range(19)]
    predict_category_property_name = ['predict_category_property'+str(i) for i in range(5)]
    item_name = ['item_sales_level', 'item_price_level', 'item_collected_level','item_pv_level','item_city_id','item_brand_id']
    item_name = item_name+item_category_list_name+item_property_list_name+predict_category_property_name

    
    user_name = ['user_gender_id','user_age_level','user_occupation_id','user_star_level']
    shop_name_old = ['shop_review_num_level','shop_review_positive_rate','shop_star_level','shop_score_service','shop_score_delivery','shop_score_description']
    id_name = ['user_id','item_id','shop_id','item_brand_id','item_city_id','context_page_id']
#    ui_name = user_name+item_name
#    si_name = shop_name + item_name
#    su_name = shop_name + user_name
    new_name = []
    lbl = preprocessing.LabelEncoder()
    print('-------------------user_name的fit_transform------------------')
    for ucol in user_name:
        data[ucol] = lbl.fit_transform(data[ucol]).astype(str)
        
    print('-------------------item_name的fit_transform------------------------')
    for icol in item_name:
        data[icol] = lbl.fit_transform(data[icol]).astype(str)
    print('-------------------id_name的fit_transform------------------------')
    for idcol in id_name:
        data[idcol] = lbl.fit_transform(data[idcol]).astype(str)
    print('-------------------对shop进行分段------------------------')
    shop_name = []
    for scol in shop_name_old:
        data['fenduna_'+scol] = pd.cut(data[scol],10,labels=[str(i) for i in range(1,11)])
        shop_name.append('fenduna_'+scol)
    print('--------------------hour_astype(str)------------------------')
    data['hour'] = data['hour'].astype(str)
    
    
    print('-------------------user和item_id特征------------------------')
    for uicol in itertools.product(user_name,item_name):
        data[uicol[0]+'_'+uicol[1]] = lbl.fit_transform(data[uicol[0]]+data[uicol[1]])
        new_name.append(uicol[0]+'_'+uicol[1])
    '''*******user+shop很废*******'''
#    print('------------------user和shop特征-----------------------')
#    for sucol in itertools.product(shop_name,user_name):
#        data[sucol[0]+'_'+sucol[1]] = lbl.fit_transform(data[sucol[0]]+data[sucol[1]])
#        new_name.append(sucol[0]+'_'+sucol[1])  
    print('------------------item和shop特征-----------------------')
    for iscol in itertools.product(shop_name,item_name):
        data[iscol[0]+'_'+iscol[1]] = lbl.fit_transform(data[iscol[0]]+data[iscol[1]])
        new_name.append(iscol[0]+'_'+iscol[1]) 
        
    '''*******id+user/item/shop很废*******'''
#    print('------------------id和user特征-----------------------')
#    for iducol in itertools.product(id_name,user_name):
#        data[iducol[0]+'_'+iducol[1]] = lbl.fit_transform(data[iducol[0]]+data[iducol[1]])
#        new_name.append(iducol[0]+'_'+iducol[1]) 
#    print('------------------id和item特征-----------------------')
#    for idicol in itertools.product(id_name,item_name):
#        data[idicol[0]+'_'+idicol[1]] = lbl.fit_transform(data[idicol[0]]+data[idicol[1]])
#        new_name.append(idicol[0]+'_'+idicol[1]) 
#    print('------------------id和shop特征-----------------------')
#    for idscol in itertools.product(id_name,item_name):
#        data[idscol[0]+'_'+idscol[1]] = lbl.fit_transform(data[idscol[0]]+data[idscol[1]])
#        new_name.append(idscol[0]+'_'+idscol[1]) 
        

    print('--------------------id和hour特征------------------------')
    for ihcol in id_name:
        data[ihcol] = lbl.fit_transform(data[ihcol]).astype(str)
        data[ihcol+'_hour'] = lbl.fit_transform(data[ihcol]+data['hour']) 
#        data[ihcol] = lbl.fit_transform(data[ihcol]).astype(int)
#        new_name.append(ihcol+'_hour')
    print('--------------------user和hour特征------------------------')
    for uhcol in user_name:
#        data[uhcol] = lbl.fit_transform(data[ihcol]).astype(str)
        data[uhcol+'_hour'] = lbl.fit_transform(data[uhcol]+data['hour']) 
    print('--------------------item和hour特征------------------------')
    for ithcol in item_name:
#        data[uhcol] = lbl.fit_transform(data[ihcol]).astype(str)
        data[ithcol+'_hour'] = lbl.fit_transform(data[ithcol]+data['hour']) 
    print('--------------------shop和hour特征------------------------')
    for shcol in shop_name:
#        data[uhcol] = lbl.fit_transform(data[ihcol]).astype(str)
        data[shcol+'_hour'] = lbl.fit_transform(data[shcol]+data['hour']) 
#    print('------------------shop和item特征------------------------')
#    for scol in shop_name:
#        data[scol] = data[scol].astype(str)
#    for sicol in itertools.product(shop_name,item_name):
#        data[sicol[0]+'_'+sicol[1]] = lbl.fit_transform(data[sicol[0]]+data[sicol[1]])
#        new_name.append(sicol[0]+'_'+sicol[1])

    print('------------------把str换回int,---------')
    print('-------------------user_name的str_int------------------')
    for ucol in user_name:
        data[ucol] = data[ucol].astype(int)
        
    print('-------------------item_name的str_int------------------------')
    for icol in item_name:
        data[icol] = data[icol].astype(int)
    print('-------------------id_name的str_int------------------------')
    for idcol in id_name:
        data[idcol] = data[idcol].astype(int)
    print('-------------------shop的str_int------------------------')
    for scol in shop_name:
        data[scol] = data[scol].astype(int)
    print('--------------------hour的str_int------------------------')
    data['hour'] = data['hour'].astype(int)
    return data

2、连续性变量的累加特征

对前面提到的4个连续型特征进行累加,试过两两累加、三三累加。效果都不好

shop_score_description、shop_score_delivery、

shop_score_service、shop_review_positive_rate



猜你喜欢

转载自blog.csdn.net/qushoushi0594/article/details/80036579