离网用户预警

读取数据

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)

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

plt.boxplot(churn['AGE'])

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

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

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

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

筛选变量

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

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

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)

抽样并进行变量聚类

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

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)

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')

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)

©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 215,723评论 6 498
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 92,003评论 3 391
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 161,512评论 0 351
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 57,825评论 1 290
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 66,874评论 6 388
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 50,841评论 1 295
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 39,812评论 3 416
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 38,582评论 0 271
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 45,033评论 1 308
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 37,309评论 2 331
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 39,450评论 1 345
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 35,158评论 5 341
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 40,789评论 3 325
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 31,409评论 0 21
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 32,609评论 1 268
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 47,440评论 2 368
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 44,357评论 2 352

推荐阅读更多精彩内容