客户流失预警模型——数据预处理与特征衍生

1.  数据预处理

1.1  极端的处理 

1、人为截断,高于某一阈值的数据,统一等于某一个数

2、删除极端值

3、单独建模型

1.2  缺失值的处理

1.2.1  种类:

1、完全随机缺失

2、随机缺失,依赖其他变量,如‘配偶姓名’的缺失取决于‘婚姻状况’

3、完全非随机缺失:缺失值是由于本身缺陷导致,如年龄较低的信用卡办卡人员不愿意透露父母亲的电话。

1.2.2  处理方法:

1、删除缺失值的属性

2、插补填充(常用于完全随机缺失且确实度不高的情形中)

3、将缺失值当成一种属性值(常用于随机缺失)

1.2.3  连续变量缺失值的处理

 一、对于完全随机缺失,当缺失率不高时,可以:

1、用常数不缺,例如均值,如果存在极端值,要考虑是否要剔除极端值后再计算均值

2、从非缺失值中随机抽样赋予缺失样本

二、对于随机缺失,可以在同一层内,用完全随机缺失的方法进行不缺。

例如:在有无工作的类别下,有工作的人群中工资样本缺失,可以用有工作人群的工资平均值进行填补

三、对于完全非随机缺失,可以当成 一种属性,将该变量转化成类别变量

1.2.4  类别变量缺失值的处理

一、当缺失率很低时:

1、用最常出现的类别补缺

2、从已知样本中随机抽样

二、当缺失率很高时:

考虑剔除该变量

三、当缺失率介于很高和很低时:

可以当成一种类别

1.3  特殊变量的处理

一、类别型变量

one—hot编码

Dummy编码

 浓度编码

WOE编码 

二、时间型变量

基于某个基准点,转化为天数

1.4  构建衍生特征

下列是一些可以解决以上问题所定义的函数,示例可看下一篇博客

import pandas as pd
import random
import numpy as np
import operator
import numbers
from sklearn.ensemble import GradientBoostingClassifer
from sklearn.model_selection import train_test_split
import datetime
import time 

#df为数据集
#col为自变量特征
#type特征为数值型还是字符串型
#method为填充方法

def MakeupMissing(df,col,type,method):
    validDf=valid.loc[df[col]==df[col]]
    if validDf.shape[0] == df.shape[0]:
        return '在以下特征中{}没有缺失值'.format(col)
    #创建一个副本,防止影响原数据框
    missingList = [i for i in df[col]]
    if type =='Continuous':
        if method not in ['Mean','Random']:
            return '请明确使用正确的方法'
        descStats=validDf[col].describe()
        mu=descStats['mean']
        std=descStats['std']
        maxVal=descStats['max']
        #根据切比雪夫不等式,超过3个标准差的数出现概率很低,基本可以推断为极端值
        if maxVal > mu+3*std:
            for i in list(validDf.index):
                if validDf.loc[i][col]>mu+3*std:
                    validDf.loc[i][col]=mu+3*std
            mu=validDf[col].describe()['mean']
        for i in range(df.shape[0]):
            if df.loc[i][col] != df.loc[i][col]:
                if method == 'Mean':
                    missingList[i]=mu
                elif method =='Random':
                    missingList[i]=random.sample(validDf[col],1)[0]
    elif type =='Categorical':
        if method not in ['Mode','Random']:
            return '请明确使用正确的方法'
        freqDict={}
        recdNum = validDf.shape[0]
        for v in set (validDf[col]):
            vDf = validDf.loc[validDf[col] == v]
            freqDict[v] = vDf.shape[0]*1.0/recdNum
        #得出众数,key指的是定义以哪个数值为评价指标
        modeVal = max(freqDict.items(),key=lambda x : x[1])[0]
        freqTuple = freqDict.items()
        freqList=[0]+[i[1] for i in freqTuple]
        freqCumsum = pd.cumsum(freqList)
        for i in range(df.shape[0]):
            if df.loc[i][col] != df.loc[i][col]:
                if method == 'Mode':
                    missingList[i]=modeVal
                elif method == 'Random':
                    a=random.random(1)
                    position=[k+1 for k in range(len(freqCumsum)-1) if freqCumsum[k] < a <=freqCumsum[k+1]][0]
                    missingList[i] = freqTuple[position-1][0]
        print('列{0}的缺失值已经用{1}方法填充'.format(col,method))
        return missingList                    
#将分类型变量编码
def Encoder(df, col, target):
    encoder = {}
    for v in set(df[col]):
        if v == v:
            subDf = df[df[col] == v]
        else:
            xList = list(df[col])
            nanInd = [i for i in range(len(xList)) if xList[i] != xList[i]]
            subDf = df.loc[nanInd]
        encoder[v] = sum(subDf[target])*1.0/subDf.shape[0]
    newCol = [encoder[i] for i in df[col]]
    return newCol
    
#日期特殊变量转换               
def DateDays(df,dateCol,base):
    base2 = time.strptime(base,'%Y/%m/%d')
    base3 = datetime.datetime(base2[0],base2[1],base2[2])
    date1 = [time.strptime(i,'%Y/%m/%d') for i in df[dateCol]]
    date2 = [datetime.datetime(i[0],i[1],i[2]) for i in date1]
    daysGap = [(date2[i] - base3).days for i in range(len(date2))]
    return daysGap

#colNumerator为分子项
#colDenominator为分母项
#特生衍生
def ColumnDivide(df, colNumerator, colDenominator):   
    N = df.shape[0]
    rate = [0]*N
    xNum = list(df[colNumerator])
    xDenom = list(df[colDenominator])
    for i in range(N):
        #这一判断主要是为了区别分母为零时无法计算的情形
        if xDenom[i]>0:
            rate[i] = xNum[i]*1.0/xDenom[i]
        else:
            rate[i] = 0
    return rate

猜你喜欢

转载自blog.csdn.net/pandacode/article/details/81741414