离网用户预警

读取数据

pandas可以读取文本文件、json、数据库、Excel等文件

使用read_csv方法读取以逗号分隔的文本文件作为DataFrame

head、tail等方法可以浏览部分数据集,可使用dtypes方法查看各列数据类型,通过astype方法修改数据类型

import pandas as pd

bill=pd.read_csv('bill.csv')#读取账单,赋值给变量bill

bill.head(5)#读取数据前5行,可以用bill.tail(5)读取最尾部5行

描述数据集

对数据的基本统计量进行计算以便初步了解数据,可以对统计量一个个单独计算,但pandas提供了一个describe函数可以一次计算多个统计量,默认计算连续型数据的统计量,要计算离散数据的统计量需要预先修改相应字段的类型,然后传入向describe函数中传入include参数

bill.dtypes#查看数据集各字段的类型

bill['IN_NETWORK_TIME']=bill['IN_NETWORK_TIME'].astype(pd.datetime)#修改入网时间为pd.datetime类型

数据选取

选择记录

通过传入true-or-false表达式选择所有结果为true的记录,例:bill[bill['PAY_SUM']>66]

选择字段

使用drop方法,它不改变原有的DataFrame中的数据,而是返回另一个DataFrame,例:newbill=bill.drop('MONTH']

使用del方法,就地删除原始DataFrame的列,一次删除一列,例:del bill['MONTH']

通过索引可以直接选择需要的列,例:bill[['ID','IN_NETWORK_TIME','IN_NET']]

通过切片选择需要的记录和字段

使用ix方法同时选取相应的记录和字段,例:bill.ix[0:1000:5,'PAY_SUM':'IN_NET':1]

bill=bill[bill['VIPFLAG']==0]#选择所有非VIP用户

bill=bill.drop(['MONTH','VIPFLAG','PRODUCT_ID'],axis=1)#drop掉MONTH、VIPFLAG、PRODUCT_ID三个不需要的列

分组汇总数据

这是在日常分析工作中运用最多的功能之一,pandas提供了groupby方法和丰富的聚合函数来实现这种功能

利用groupby方法生成DataFrameGroupBy对象.

应用聚合函数对DataFrameGroupBY对象进行聚合,常用的pandas聚合函数包括经过优化的count sum mean median min max std等,也可使用自定义函数进行聚合,只需将函数传入agg方法即可,详见pandas文档

 1. 使用groupby方法生成一个DataFrameGroupBy对象

bill.groupby('USER_STATE')#仅按’USER_STATE'进行汇总,也可同时按多列汇总,见下例

2.应用聚合函数对DataFrameGroupBY对象进行聚合

bill[['PAY_SUM','TRAFFIC_SUM','CALL_SUM']].groupby([bill['USER_STATE'],bill['IN_NET']]).mean()

生成透视表/交叉表

透视表/交叉表比汇总表可读性更高,生成的报表往往采用透视表/交叉表的形式

DataFrame提供了实例方法pivot_table来生成透视表/交叉表,pandas.pivot_table是一个能实现同样功能的顶级函数,另外pandas.crosstab是专用于生成交叉表的函数

bill.pivot_table(['PAY_SUM','TRAFFIC_SUM','CALL_SUM'],index='USER_STATE',columns='IN_NET',aggfunc='mean')

pd.crosstab(bill['IN_NET'],bill['USER_STATE'])

去重

使用drop_duplicates方法返回一个不含重复项的DataFrame,默认识别所有列,也可单独指定要区分的列

call_detail=pd.read_csv('call_detail.csv')#读取通话详单,赋值给变量call_detail

cd=call_detail[['ID','IMSI','IMEI']].drop_duplicates('ID')

连接/合并数据

进行数据分析时,数据经常来源于不同的文件,需要将这些表连接/合并起来,放在一张表中进行分析

横向连接:将不同的表按照关键字连接起来,包括内连接、外连接、左连接、右连接等,进行一对一的连接时,最好先去重数据集

pd.merge(left,right,how,on,left_on,right_on),其中how:{'inner','outer','left','right'},默认为'inner',可按多个关键字合并

纵向合并:将数张表纵向合并起来,例如将一月和二月销售数据具有相同的列,可将二者纵向合并

pd.concat(objs,axis=0,ignore_index=False),其中objs:表变量组成的列表,例:pd.concat([cd,cd])

mt=pd.merge(bill,cd,on='ID')

数据转换

原始数据需要经过转换才能符合建模需求,例如:生成新字段、重新分类、变换哑变量、去除重复数据、过滤极端\异常值、填补缺失值、变量聚类、离散化等

mt['IMEI']=mt['IMEI'].fillna(0)#将IMEI空值填为0

mt['TAC']=mt['IMEI'].map(lambda x:str(x)[:6])#对字符串操作,生成新列'TAC'

mt['Z_PAY']=(mt['PAY_SUM']-mt['PAY_SUM'].mean())/mt['PAY_SUM'].std()#对数值操作,生成新列'Z_PAY'

from datetime import datetime,timedelta

mt['U_duration']=map(lambda x:x.days/30.,datetime(2014,11,1)-pd.to_datetime(mt['IN_NETWORK_TIME']))#时间函数生成新列

mt['USER_STATE']=mt['USER_STATE'].replace([2,3,4,5,6,7],2)#用替换值的方式合并不同分类水平,也可用于填补空值

mt['TRAFFIC_SUM'][mt['TRAFFIC_SUM']>2000]=2000#盖帽法处理极端值,会产生警告信息

new_mt=mt.join(pd.get_dummies(mt['USER_STATE'],prefix='U_S'))#生成哑变量

new_mt.describe(include='all').T

数据探索

除了describe计算基本统计量外,还需要探索目标变量和自变量以及自变量之间的关系,以决定哪些变量入选模型,这种数据探索往往结合图形来说明

常用的绘图包包括matplotlib、seaborn等

churn=pd.read_csv('telecom_churn.csv') 读取已经整理好的数据

仅对部分分类变量进行了指定

churn['gender']=churn['gender'].astype('category')

churn['edu_class']=churn['edu_class'].astype('category')

churn['feton']=churn['feton'].astype('category')

churn.describe(include='all')

import math

import numpy as np

import matplotlib.pyplot as plt

%matplotlib inline

import seaborn as sns

from scipy import stats,integrate

import statsmodels.api as sm

sns.distplot(churn['duration'],fit=stats.norm)

离网用户预警_第1张图片

sns.distplot(np.log(churn['duration']),kde=True,fit=stats.norm)

离网用户预警_第2张图片

plt.boxplot(churn['AGE'])

离网用户预警_第3张图片

sns.barplot(x='edu_class',y='churn',data=churn)

离网用户预警_第4张图片

sns.barplot(x='churn', y='peakMinDiff',hue=None,data=churn)

离网用户预警_第5张图片

sns.jointplot(x='duration', y='AGE', data=churn,kind='kde')

离网用户预警_第6张图片

sns.boxplot(x='churn', y='duration',hue='edu_class',data=churn)

离网用户预警_第7张图片

筛选变量

筛选变量时可以应用专业知识,选取与目标字段相关性较高的字段用于建模,也可通过分析现有数据,用统计量辅助选择

为了增强模型稳定性,自变量之间最好相互独立,可运用统计方法选择要排除的变量或进行变量聚类

corrmatrix=churn.corr(method='spearman')

spearman相关系数矩阵,可选pearson相关系数,目前仅支持这两种,函数自动排除category类型

corrmatrix[np.abs(corrmatrix)>0.5]

选取相关系数绝对值大于0.5的变量,仅为了方便查看

为了增强模型稳定,根据上述相关性矩阵,除'posTrend','planChange','nrProm','curPlan'几个变量

sampler = np.random.randint(0,len(churn),size=50) 

随机数列表

clustertable=churn[['AGE','peakMinAv','peakMinDiff','incomeCode','duration']]

选取连续型变量

sns.clustermap(clustertable.iloc[sampler].T, col_cluster=False, row_cluster=True)

抽样并进行变量聚类

离网用户预警_第8张图片

连续型变量往往是模型不稳定的原因,同时模型解释时也更困难,可通过离散化变换为分类变量

churn['duration_bins']=pd.qcut(churn.duration,14)

将duration字段切分为数量(大致)相等的14段

churn['churn'].astype('int64').groupby(churn['duration_bins']).agg(['count','mean']).T

bins = [0,4,8,12,22,73]

churn['duration_bins'] = pd.cut(churn['duration'],bins,labels=False)

churn['churn'].astype('int64').groupby(churn['duration_bins']).agg(['mean','count'])

根据卡方值选择与目标关联较大的分类变量

计算卡方值需要应用到sklearn模块,但该模块当前版本不支持pandas的category类型变量,会出现警告信息,可忽略该警告或将变量转换为int类型

import sklearn.feature_selection as feature_selection

churn['gender']=churn['gender'].astype('int')

churn['edu_class']=churn['edu_class'].astype('int')

churn['feton']=churn['feton'].astype('int')

feature_selection.chi2(churn[['gender','edu_class','feton','prom','posPlanChange',

                              'duration_bins','curPlan','call_10086']],churn['churn'])

选取部分字段进行卡方检验

根据结果显示,'prom'、'posPlanChange'、'curPlan'字段可以考虑排除

建模¶

根据数据分析结果选取建模所需字段,同时抽取一定数量的记录作为建模数据

将建模数据划分为训练集和测试集

选择模型进行建模

#根据模型不同,对自变量类型的要求也不同,为了示例,本模型仅引入'AGE'这一个连续型变量

model_data=churn[['subscriberID','churn','gender','edu_class','feton','duration_bins']]

model_data=churn[['subscriberID','churn','gender','edu_class','feton','duration_bins','call_10086','AGE']]

第二可选方案

target = model_data['churn']#选取目标变量

data=model_data.ix[:,'gender':]#选取自变量

import sklearn.cross_validation as cross_validation

train_data,test_data,train_target,test_target=cross_validation.train_test_split(data,target,test_size=0.4,

                                                                                train_size=0.6

                                                                                ,random_state=12345)#划分训练集和测试集

选择决策树进行建模

import sklearn.tree as tree

clf=tree.DecisionTreeClassifier(criterion='entropy', max_depth=8, min_samples_split=5)#当前支持计算信息增益和GINI

clf.fit(train_data,train_target)#使用训练数据建模

#查看模型预测结果

train_est=clf.predict(train_data)#用模型预测训练集的结果

train_est_p=clf.predict_proba(train_data)[:,1]#用模型预测训练集的概率

test_est=clf.predict(test_data)#用模型预测测试集的结果

test_est_p=clf.predict_proba(test_data)[:,1]#用模型预测测试集的概率

pd.DataFrame({'test_target':test_target,'test_est':test_est,'test_est_p':test_est_p}).T#查看测试集预测结果与真实结果对比

模型评估

import sklearn.metrics as metrics

print (metrics.confusion_matrix(test_target, test_est,labels=[0,1]))#混淆矩阵

print (metrics.classification_report(test_target, test_est))#计算评估指标

print (pd.DataFrame(zip(data.columns,clf.feature_importances_)))#变量重要性指标

red, blue = sns.color_palette("Set1",2)

sns.kdeplot(test_est_p[test_target==1], shade=True, color=red)

sns.kdeplot(test_est_p[test_target==0], shade=True, color=blue)

离网用户预警_第9张图片

fpr_test, tpr_test, th_test = metrics.roc_curve(test_target, test_est_p)

fpr_train, tpr_train, th_train = metrics.roc_curve(train_target, train_est_p)

plt.figure(figsize=[6,6])

plt.plot(fpr_test, tpr_test, color=blue)

plt.plot(fpr_train, tpr_train, color=red)

plt.title('ROC curve')

离网用户预警_第10张图片

tree.export_graphviz(clf,out_file='tree.dot')#查看树结构

模型保存/读取

import pickle as pickle

model_file = open(r'clf.model', 'wb')

pickle.dump(clf, model_file)

model_file.close()

model_load_file = open(r'clf.model', 'rb')

model_load = pickle.load(model_load_file)

model_load_file.close()

test_est_load = model_load.predict(test_data)

pd.crosstab(test_est_load,test_est)

你可能感兴趣的:(离网用户预警)