电信用户流失预测案例(1)
【Kaggle】Telco Customer Churn 電信用戶流失預(yù)測(cè)案例
前言:案例學(xué)習(xí)說(shuō)明與案例建模流程
??在學(xué)習(xí)了經(jīng)典機(jī)器學(xué)習(xí)算法和Scikit-Learn的調(diào)參策略之后,接下來(lái),我們將把此前所學(xué)到的內(nèi)容應(yīng)用到實(shí)踐當(dāng)中去。從本節(jié)開始,我們將圍繞Kaggle中的電信用戶流失數(shù)據(jù)集(Telco Customer Churn)進(jìn)行用戶流失預(yù)測(cè)。在此過(guò)程中,我們將綜合應(yīng)用此前所介紹的各種方法與技巧,并在實(shí)踐中提煉總結(jié)更多實(shí)用技巧。
??對(duì)于實(shí)戰(zhàn)案例的講解,我們將分為三個(gè)階段進(jìn)行,當(dāng)然這也是我們?cè)趨⑴c算法競(jìng)賽、或者在實(shí)際算法建模時(shí)的一般流程:
- Stage 1.業(yè)務(wù)背景解讀與數(shù)據(jù)探索
??在拿到數(shù)據(jù)(接受任務(wù))的第一時(shí)間,需要對(duì)數(shù)據(jù)(也就是對(duì)應(yīng)業(yè)務(wù))的基本背景進(jìn)行解讀。由于任何數(shù)據(jù)都誕生于某業(yè)務(wù)場(chǎng)景下,同時(shí)也是根據(jù)某些規(guī)則來(lái)進(jìn)行的采集或者計(jì)算得出,因此如果可以,我們應(yīng)當(dāng)盡量去了解數(shù)據(jù)誕生的基本環(huán)境和對(duì)應(yīng)的業(yè)務(wù)邏輯,盡可能準(zhǔn)確的解讀每個(gè)字段的含義,而只有在無(wú)法獲取真實(shí)業(yè)務(wù)背景時(shí),才會(huì)考慮退而求其次通過(guò)數(shù)據(jù)情況去倒推業(yè)務(wù)情況。
??當(dāng)然,在進(jìn)行了數(shù)據(jù)業(yè)務(wù)背景解讀后,接下來(lái)就需要對(duì)拿到的數(shù)據(jù)進(jìn)行基本的數(shù)據(jù)探索。一般來(lái)說(shuō),數(shù)據(jù)探索包括數(shù)據(jù)分布檢驗(yàn)、數(shù)據(jù)正確性校驗(yàn)、數(shù)據(jù)質(zhì)量檢驗(yàn)、訓(xùn)練集/測(cè)試集規(guī)律一致性檢驗(yàn)等。當(dāng)然,這里可能涉及到的操作較多,也并非所有的操作都必須在一次建模過(guò)程中全部完成。但作為教學(xué)案例,我們將在后續(xù)的內(nèi)容中詳細(xì)介紹每個(gè)環(huán)節(jié)的相關(guān)操作及目的。 - Stage 2.數(shù)據(jù)預(yù)處理與特征工程
??在了解了建模業(yè)務(wù)背景和基本數(shù)據(jù)情況后,接下來(lái)我們就需要進(jìn)行實(shí)際建模前的“數(shù)據(jù)準(zhǔn)備”工作了,也就是數(shù)據(jù)預(yù)處理(數(shù)據(jù)清洗)與特征工程。其中,數(shù)據(jù)清洗主要聚焦于數(shù)據(jù)集數(shù)據(jù)質(zhì)量提升,包括缺失值、異常值、重復(fù)值處理,以及數(shù)據(jù)字段類型調(diào)整等;而特征工程部分則更傾向于調(diào)整特征基本結(jié)構(gòu),來(lái)使數(shù)據(jù)集本身規(guī)律更容易被模型識(shí)別,如特征衍生、特殊類型字段處理(包括時(shí)序字段、文本字段等)等。
??當(dāng)然,很多時(shí)候我們并不刻意區(qū)分?jǐn)?shù)據(jù)清洗與特征工程之間的區(qū)別,很多時(shí)候數(shù)據(jù)清洗的工作也可以看成是特征工程的一部分。同時(shí),也有很多時(shí)候我們也不會(huì)一定要求在不同階段執(zhí)行不同操作,例如如果在數(shù)據(jù)探索時(shí)發(fā)現(xiàn)缺失值比例較小,則可以直接對(duì)其進(jìn)行均值/眾數(shù)填補(bǔ),而不用等到特征工程階段統(tǒng)一處理,再例如很多特征工程的方法需要結(jié)合實(shí)際建模效果來(lái)判別,所以有的時(shí)候特征衍生也會(huì)和建模過(guò)程交替進(jìn)行。 - Stage 3.算法建模與模型調(diào)優(yōu)
??在經(jīng)過(guò)一系列準(zhǔn)備工作后,就將進(jìn)入到最終建模環(huán)節(jié)了,建模過(guò)程既包括算法訓(xùn)練也包括參數(shù)調(diào)優(yōu)。當(dāng)然,很多時(shí)候建模工作不會(huì)一蹴而就,需要反復(fù)嘗試各種模型、各種調(diào)參方法、以及模型融合方法。此外,很多時(shí)候我們也需要根據(jù)最終模型輸出結(jié)果來(lái)進(jìn)行數(shù)據(jù)預(yù)處理和特征工程相關(guān)方法調(diào)整。
??上述流程可以用如下流程圖進(jìn)行表示:
??本節(jié)我們將先從數(shù)據(jù)集業(yè)務(wù)背景開始介紹,并簡(jiǎn)單討論如何借助Kaggle平臺(tái)獲取更多幫助。同時(shí)我們也將圍繞獲取到的數(shù)據(jù)進(jìn)行數(shù)據(jù)探索。
Part 1.數(shù)據(jù)背景介紹與數(shù)據(jù)探索
一、業(yè)務(wù)背景與數(shù)據(jù)背景
1.數(shù)據(jù)集基本情況與數(shù)據(jù)集獲取方法
??本次案例的數(shù)據(jù)源自Kaggle平臺(tái)上分享的建模數(shù)據(jù)集:Telco Customer Churn,該數(shù)據(jù)集描述了某電信公司的用戶基本情況,包括每位用戶已注冊(cè)的相關(guān)服務(wù)、用戶賬戶信息、用戶人口統(tǒng)計(jì)信息等,當(dāng)然,也包括了最為核心的、也是后續(xù)建模需要預(yù)測(cè)的標(biāo)簽字段——用戶流失情況(Churn)。
??需要注意的是,該數(shù)據(jù)并非競(jìng)賽數(shù)據(jù)集,而是Kaggle分享的一個(gè)高投票數(shù)據(jù)集(1788 votes),是Kaggle平臺(tái)上非常經(jīng)典的圍繞偏態(tài)數(shù)據(jù)集建模的數(shù)據(jù)集。該數(shù)據(jù)源自IBM商業(yè)社區(qū)(IBM Business Analytics Community)上分享的數(shù)據(jù)集,用于社區(qū)成員內(nèi)部學(xué)習(xí)使用。
??根據(jù)IBM商業(yè)社區(qū)分享團(tuán)隊(duì)描述,該數(shù)據(jù)集為某電信公司在加利福尼亞為7000余位用戶(個(gè)人/家庭)提供電話和互聯(lián)網(wǎng)服務(wù)的相關(guān)記錄。由于該數(shù)據(jù)集并不是競(jìng)賽數(shù)據(jù)集,因此數(shù)據(jù)集的下載方式相對(duì)容易,官網(wǎng)也只提供了網(wǎng)頁(yè)下載一種選項(xiàng)(無(wú)法通過(guò)命令行直接下載)。我們可以在該數(shù)據(jù)集的Kaggle主頁(yè)看到數(shù)據(jù)集的相關(guān)信息以及下載地址。此處我們簡(jiǎn)單介紹關(guān)于Kaggle數(shù)據(jù)集頁(yè)面的基本功能,既Kaggle平臺(tái)的基本使用方法,在后續(xù)的課程學(xué)習(xí)中,若是Kaggle案例,我們也將頻繁借助Kaggle主頁(yè)來(lái)獲取幫助。當(dāng)然,熟練使用Kaggle主頁(yè)獲取數(shù)據(jù)和挖掘信息(而不是借助第三方渠道),也是算法工程師必備技能之一。
- 數(shù)據(jù)集主頁(yè)
??首先是數(shù)據(jù)集主頁(yè):
??此處我們能大致看到數(shù)據(jù)集基本信息,如總共只有一個(gè)數(shù)據(jù)文件(在其他很多情況下,一個(gè)建模目標(biāo)可能會(huì)包含多個(gè)數(shù)據(jù)集),總共21列,7043條數(shù)據(jù),以及其他各列的一些基本統(tǒng)計(jì)信息等。
??當(dāng)然,在數(shù)據(jù)集主頁(yè)上,我們可以直接點(diǎn)擊下載按鈕進(jìn)行數(shù)據(jù)集下載。下載完成后將其放到當(dāng)前操作主目錄下進(jìn)行讀取:
在其他一些情況下,我們可能需要借助命令行來(lái)進(jìn)行數(shù)據(jù)集下載和建模結(jié)果提交,相關(guān)內(nèi)容我們將在后續(xù)介紹競(jìng)賽數(shù)據(jù)集時(shí)詳細(xì)討論。
- Discussion頁(yè)面
??此外,我們還能夠在Discussion頁(yè)面中看到圍繞該建模問(wèn)題的相關(guān)討論。值得一提的是,在很多場(chǎng)合下(尤其是在參加算法競(jìng)賽時(shí)),Discussion頁(yè)面中的討論帖都是重要的信息獲取渠道,其中不乏一些官方給出的補(bǔ)充問(wèn)答內(nèi)容、一些競(jìng)賽大神給出的自己的賽題理解、以及一些參賽者獨(dú)到的討論和見(jiàn)解。而從中快速捕獲信息,則能幫助你迅速建立信息優(yōu)勢(shì)。
??例如在本數(shù)據(jù)集相關(guān)的討論中,就有關(guān)于用戶流失業(yè)務(wù)背景的相關(guān)討論。其內(nèi)較為具體的說(shuō)明了到底什么是用戶流失、為什么要關(guān)注用戶流失,以及圍繞用戶流失在進(jìn)行建模時(shí),最好關(guān)注那些模型評(píng)估指標(biāo)。當(dāng)然,這些內(nèi)容我們也將隨后詳細(xì)探討。
- Code頁(yè)面
??此外,我們還能夠在code頁(yè)面看到其他用戶分享的代碼,其中也不乏一些精彩的思路和方法,也有很多可以借鑒和學(xué)習(xí)的內(nèi)容。比如在該數(shù)據(jù)集的Code頁(yè)面,就有很多同學(xué)會(huì)比較關(guān)注的處理樣本不均衡的SHAP方法,以及該方法配合集成學(xué)習(xí)的使用方法:
當(dāng)然,Kaggle平臺(tái)上也有很多帶有廣告性質(zhì)的內(nèi)容,需要進(jìn)行甄別。
2.用戶流失業(yè)務(wù)背景與建模目標(biāo)
- 電信業(yè)務(wù)基本背景介紹
??在基本了解Kaggle平臺(tái)使用方法以及獲取到建模數(shù)據(jù)集之后,接下來(lái)我們需要圍繞電信用戶流失這一基本業(yè)務(wù)背景來(lái)進(jìn)行介紹,同時(shí)解釋本案例的最終建模目標(biāo)。
??我們知道,電信作為公共網(wǎng)絡(luò)、數(shù)據(jù)傳輸、電話語(yǔ)音通信等基礎(chǔ)服務(wù)提供方,一直以來(lái)都是國(guó)家支柱產(chǎn)業(yè)之一。而伴隨著移動(dòng)互聯(lián)網(wǎng)的普及、數(shù)字經(jīng)濟(jì)蓬勃發(fā)展,網(wǎng)絡(luò)這一基礎(chǔ)設(shè)施也愈發(fā)重要。有個(gè)非常形象的比喻,在過(guò)去,斷電會(huì)導(dǎo)致工廠停產(chǎn)、造成重大的經(jīng)濟(jì)損失,而現(xiàn)在,中斷網(wǎng)絡(luò)數(shù)字傳輸,則足以讓某些企業(yè)一夜損失上億。
??簡(jiǎn)而言之,在一定程度上,網(wǎng)絡(luò)的質(zhì)量和速度甚至?xí)苯記Q定著數(shù)字經(jīng)濟(jì)發(fā)展的質(zhì)量和速度。而伴隨著5G時(shí)代的到來(lái),5G的工業(yè)化應(yīng)用,如車聯(lián)網(wǎng)、物聯(lián)網(wǎng)、工業(yè)互聯(lián)網(wǎng)等,也將在未來(lái)發(fā)展成為萬(wàn)億規(guī)模產(chǎn)業(yè),并且增強(qiáng)寬帶、海量連接、低延時(shí)、高可靠的網(wǎng)絡(luò)基礎(chǔ)設(shè)施,將為構(gòu)建物聯(lián)網(wǎng)、人工智能等技術(shù)體系提供保障。
??而在此背景下,電信市場(chǎng)的競(jìng)爭(zhēng)也愈發(fā)激烈。一般來(lái)說(shuō)電信領(lǐng)域的運(yùn)營(yíng)商在3-4家時(shí)能保持一個(gè)健康的市場(chǎng)競(jìng)爭(zhēng)狀態(tài),而在國(guó)內(nèi),5G的運(yùn)營(yíng)商牌照也頒發(fā)了四家,除了三大運(yùn)營(yíng)商外(電信、聯(lián)通、移動(dòng)),還有中國(guó)廣電。而在數(shù)字時(shí)代,傳統(tǒng)的大眾營(yíng)銷已經(jīng)失去優(yōu)勢(shì),如何基于用戶信息和行為,來(lái)進(jìn)行更加精準(zhǔn)的營(yíng)銷,從而滿足用戶更加多樣化、層次化和個(gè)性化的需求,成為所有電信運(yùn)營(yíng)商必須面對(duì)的課題。而于此同時(shí),電信的公共客戶(個(gè)人或家庭用戶)用戶又同時(shí)具有易變性、發(fā)展性和替代性等特點(diǎn),且用戶需求彈性較小,外加普通用戶購(gòu)買電信產(chǎn)品周期較長(zhǎng),導(dǎo)致在實(shí)際的交易關(guān)系中,電信公司對(duì)公共客戶獲客較難、主動(dòng)拓展新用戶成本較高,因此維系既有用戶、防止用戶流失就成了重要的運(yùn)營(yíng)策略。
??當(dāng)然,對(duì)于電信運(yùn)營(yíng)商來(lái)說(shuō),用戶流失有很多偶然因素,不過(guò)通過(guò)對(duì)用戶屬性和行為的數(shù)字化描述,我們或許也能夠在這些數(shù)據(jù)中,挖掘?qū)е掠脩袅魇У摹爸虢z馬跡”,并且更重要的一點(diǎn),如果能夠?qū)崟r(shí)接入這些數(shù)據(jù),或許還能夠進(jìn)一步借助模型來(lái)對(duì)未來(lái)用戶流失的風(fēng)險(xiǎn)進(jìn)行預(yù)測(cè),從而及時(shí)制定挽留策略,來(lái)防止用戶真實(shí)流失情況發(fā)生。
- 機(jī)器學(xué)習(xí)建模目標(biāo)
??也就是說(shuō),在此背景下,實(shí)際的算法建模目標(biāo)有兩個(gè),其一是對(duì)流失用戶進(jìn)行預(yù)測(cè),其二則是找出影響用戶流失的重要因子,來(lái)輔助運(yùn)營(yíng)人員來(lái)進(jìn)行營(yíng)銷策略調(diào)整或制定用戶挽留措施。
??綜合上述兩個(gè)目標(biāo)我們不難發(fā)現(xiàn),我們要求模型不僅要擁有一定的預(yù)測(cè)能力,并且能夠輸出相應(yīng)的特征重要性排名,并且最好能夠具備一定的可解釋性,也就是能夠較為明顯的闡述特征變化是如何影響標(biāo)簽取值變化的。據(jù)此要求,我們首先可以考慮邏輯回歸模型。邏輯回歸的線性方程能夠提供非常好的結(jié)果可解釋性,同時(shí)我們也可以通過(guò)邏輯回歸中的正則化項(xiàng)也可以用于評(píng)估特征重要性。
??當(dāng)然,此外我們也可以考慮構(gòu)建決策樹即集成模型來(lái)解決該問(wèn)題。決策樹同樣具有較好的可解釋性,并且也可以根據(jù)樹模型中的信息熵(或者基尼系數(shù))的下降情況來(lái)進(jìn)行特征重要性評(píng)估。
二、數(shù)據(jù)解讀與預(yù)處理
??在基本了解業(yè)務(wù)背景和建模目標(biāo)之后,我們開始圍繞數(shù)據(jù)集進(jìn)行解讀和探索。
1.字段解釋
??首先是圍繞數(shù)據(jù)集字段含義進(jìn)行解釋。該數(shù)據(jù)集并沒(méi)有提供相應(yīng)的數(shù)據(jù)字典作為不同字段的解釋,但由于數(shù)據(jù)集并沒(méi)有匿名字段,所以基本可以根據(jù)字段的名稱給出相應(yīng)的解釋:
tcc.info() # <class 'pandas.core.frame.DataFrame'> # RangeIndex: 7043 entries, 0 to 7042 # Data columns (total 21 columns): # # Column Non-Null Count Dtype # --- ------ -------------- ----- # 0 customerID 7043 non-null object # 1 gender 7043 non-null object # 2 SeniorCitizen 7043 non-null int64 # 3 Partner 7043 non-null object # 4 Dependents 7043 non-null object # 5 tenure 7043 non-null int64 # 6 PhoneService 7043 non-null object # 7 MultipleLines 7043 non-null object # 8 InternetService 7043 non-null object # 9 OnlineSecurity 7043 non-null object # 10 OnlineBackup 7043 non-null object # 11 DeviceProtection 7043 non-null object # 12 TechSupport 7043 non-null object # 13 StreamingTV 7043 non-null object # 14 StreamingMovies 7043 non-null object # 15 Contract 7043 non-null object # 16 PaperlessBilling 7043 non-null object # 17 PaymentMethod 7043 non-null object # 18 MonthlyCharges 7043 non-null float64 # 19 TotalCharges 7043 non-null object # 20 Churn 7043 non-null object # dtypes: float64(1), int64(2), object(18) # memory usage: 1.1+ MB根據(jù)Kaggle的數(shù)據(jù)集介紹,以及IBM商業(yè)分析社區(qū)中提供的解釋,數(shù)據(jù)集中各字段解釋如下:
| customerID | 用戶ID |
| gender | 性別 |
| SeniorCitizen | 是否是老年人(1代表是) |
| Partner | 是否有配偶(Yes or No) |
| Dependents | 是否經(jīng)濟(jì)獨(dú)立(Yes or No) |
| tenure | 用戶入網(wǎng)時(shí)間 |
| PhoneService | 是否開通電話業(yè)務(wù)(Yes or No) |
| MultipleLines | 是否開通多條電話業(yè)務(wù)(Yes 、 No or No phoneservice) |
| InternetService | 是否開通互聯(lián)網(wǎng)服務(wù)(No、DSL數(shù)字網(wǎng)絡(luò)或filber potic光線網(wǎng)絡(luò)) |
| OnlineSecurity | 是否開通網(wǎng)絡(luò)安全服務(wù)(Yes、No or No internetservice) |
| OnlineBackup | 是否開通在線備份服務(wù)(Yes、No or No internetservice) |
| DeviceProtection | 是否開通設(shè)備保護(hù)服務(wù)(Yes、No or No internetservice) |
| TechSupport | 是否開通技術(shù)支持業(yè)務(wù)(Yes、No or No internetservice) |
| StreamingTV | 是否開通網(wǎng)絡(luò)電視(Yes、No or No internetservice) |
| StreamingMovies | 是否開通網(wǎng)絡(luò)電影(Yes、No or No internetservice) |
| Contract | 合同簽訂方式(按月、按年或者兩年) |
| PaperlessBilling | 是否開通電子賬單(Yes or No) |
| PaymentMethod | 付款方式(bank transfer、credit card、electronic check、mailed check) |
| MonthlyCharges | 月度費(fèi)用 |
| TotalCharges | 總費(fèi)用 |
| Churn | 是否流失(Yes or No) |
同時(shí),根據(jù)官方給出的數(shù)據(jù)集說(shuō)明,上述字段基本可以分為三類,分別是用戶已注冊(cè)的服務(wù)信息、用戶賬戶信息和用戶人口統(tǒng)計(jì)信息,三類字段劃分情況如下:
2.數(shù)據(jù)質(zhì)量探索
??在了解數(shù)據(jù)集字段含義后,首先我們需要對(duì)數(shù)據(jù)集的數(shù)據(jù)質(zhì)量進(jìn)行探索,這也是數(shù)據(jù)探索的最基礎(chǔ)的角度。
- 數(shù)據(jù)集正確性校驗(yàn)
??首先是數(shù)據(jù)集正確性校驗(yàn)。一般來(lái)說(shuō)數(shù)據(jù)集正確性校驗(yàn)分為兩種,其一是檢驗(yàn)數(shù)據(jù)集字段是否和數(shù)據(jù)字典中的字段一致,其二則是檢驗(yàn)數(shù)據(jù)集中ID列有無(wú)重復(fù)。由于該數(shù)據(jù)集并為提供數(shù)據(jù)字典,因此此處主要校驗(yàn)數(shù)據(jù)集ID有無(wú)重復(fù):
tcc['customerID'].nunique() == tcc.shape[0] #True另外的方法
tcc['customerID'].unique() #array(['7590-VHVEG', '5575-GNVDE', '3668-QPYBK', ..., '4801-JZAZL', # '8361-LTMKD', '3186-AJIEK'], dtype=object) tcc['customerID'].nunique() #7043 len(set(tcc["customerID"])) #7043 tcc.shape #(7043, 21)當(dāng)然,ID列沒(méi)有重復(fù),則數(shù)據(jù)集中也不存在完全重復(fù)的兩行數(shù)據(jù):
tcc.duplicated().sum() #數(shù)據(jù)中有沒(méi)有重復(fù)的兩行 #0- 數(shù)據(jù)缺失值檢驗(yàn)
??接下來(lái)進(jìn)一步檢查數(shù)據(jù)集缺失情況,我們可以通過(guò)isnull來(lái)快速查看數(shù)據(jù)集缺失情況:
tcc.isnull().sum() # customerID 0 # gender 0 # SeniorCitizen 0 # Partner 0 # Dependents 0 # tenure 0 # PhoneService 0 # MultipleLines 0 # InternetService 0 # OnlineSecurity 0 # OnlineBackup 0 # DeviceProtection 0 # TechSupport 0 # StreamingTV 0 # StreamingMovies 0 # Contract 0 # PaperlessBilling 0 # PaymentMethod 0 # MonthlyCharges 0 # TotalCharges 0 # Churn 0 # dtype: int64 '''也可以tcc.info()'''此外,我們也可以通過(guò)定義如下函數(shù)來(lái)輸出更加完整的每一列缺失值的數(shù)值和占比:
def missing (df):"""計(jì)算每一列的缺失值及占比"""missing_number = df.isnull().sum().sort_values(ascending=False) # 每一列的缺失值求和后降序排序 missing_percent = (df.isnull().sum()/df.isnull().count()).sort_values(ascending=False) # 每一列缺失值占比missing_values = pd.concat([missing_number, missing_percent], axis=1, keys=['Missing_Number', 'Missing_Percent']) # 合并為一個(gè)DataFramereturn missing_valuesmissing(tcc)此外,在info返回的信息中的non-null也能看出數(shù)據(jù)集不存在缺失值。
從上述結(jié)果能看出,數(shù)據(jù)集不存在缺失值。
沒(méi)有缺失只代表數(shù)據(jù)集中沒(méi)有None或者Nan,并不排除可能存在用別的值表示缺失值的情況,稍后我們將對(duì)其進(jìn)行進(jìn)一步分析。
3.字段類型探索
??接下來(lái),我們將進(jìn)一步圍繞數(shù)據(jù)集的字段類型來(lái)進(jìn)行調(diào)整。
- 時(shí)序字段處理
??根據(jù)數(shù)據(jù)集info我們發(fā)現(xiàn),大多數(shù)字段都屬于離散型字段,并且object類型居多。對(duì)于建模分析來(lái)說(shuō),我們是無(wú)法直接使用object類型對(duì)象的,因此需要對(duì)其進(jìn)行類型轉(zhuǎn)化,通常來(lái)說(shuō),我們會(huì)將字段劃分為連續(xù)型字段和離散型字段,并且根據(jù)離散字段的具體含義來(lái)進(jìn)一步區(qū)分是名義型變量還是有序變量。不過(guò)在劃分連續(xù)/離散字段之前,我們發(fā)現(xiàn)數(shù)據(jù)集中存在一個(gè)入網(wǎng)時(shí)間字段,看起來(lái)像是時(shí)序字段。需要注意的是,從嚴(yán)格意義上來(lái)說(shuō),用時(shí)間標(biāo)注的時(shí)序字段即不數(shù)據(jù)連續(xù)型字段或離散型字段(盡管可以將其看成是離散字段,但這樣做會(huì)損失一些信息),因此我們需要重點(diǎn)關(guān)注入網(wǎng)時(shí)間字段是否是時(shí)間標(biāo)注的字段:
tcc['tenure'] # 0 1 # 1 34 # 2 2 # 3 45 # 4 2 # .. # 7038 24 # 7039 72 # 7040 11 # 7041 4 # 7042 66 # Name: tenure, Length: 7043, dtype: int64簡(jiǎn)單查看我們發(fā)現(xiàn),該字段并不是典型的用年月日標(biāo)注的時(shí)間字段,如2020-08-01,而是一串連續(xù)的數(shù)值。當(dāng)然,我們可以進(jìn)一步查看該字段的取值范圍:
tcc['tenure'].nunique() #73該字段總共有73個(gè)不同的取值,結(jié)合此前所說(shuō),數(shù)據(jù)集是第三季度的用戶數(shù)據(jù),因此我們推斷該字段應(yīng)該是經(jīng)過(guò)字典排序后的離散型字段。所謂字典排序,其本質(zhì)是一種離散變量的轉(zhuǎn)化方式,有時(shí)我們也可以將時(shí)序數(shù)據(jù)進(jìn)行字典排序,該過(guò)程我們可以通過(guò)如下示例進(jìn)行說(shuō)明:
也就是說(shuō),在第三季度中,這些用戶的行為發(fā)生在某73天內(nèi),因此入網(wǎng)時(shí)間字段有73個(gè)取值。不過(guò)由于該字段是經(jīng)過(guò)字典排序后的結(jié)果,因此已經(jīng)損失了原始信息,即每位用戶實(shí)際的入網(wǎng)時(shí)間。而在實(shí)際的分析過(guò)程中,我們可以轉(zhuǎn)化后的入網(wǎng)時(shí)間字段看成是離散變量,當(dāng)然也可以將其視作連續(xù)變量來(lái)進(jìn)行分析,具體選擇需要依據(jù)模型來(lái)決定。此處我們先將其視作離散變量,后續(xù)根據(jù)情況來(lái)進(jìn)行調(diào)整。
關(guān)于字典排序的代碼實(shí)現(xiàn)方法會(huì)在后續(xù)進(jìn)行介紹。
- 連續(xù)/離散型變量標(biāo)注
??接下來(lái),我們來(lái)標(biāo)注每一列的數(shù)據(jù)類型,我們可以通過(guò)不同列表來(lái)存儲(chǔ)不同類型字段的名稱:
# 離散字段 category_cols = ['customerID', 'gender', 'SeniorCitizen', 'Partner', 'Dependents', 'tenure', 'PhoneService', 'MultipleLines', 'InternetService', 'OnlineSecurity', 'OnlineBackup', 'DeviceProtection', 'TechSupport', 'StreamingTV', 'StreamingMovies', 'Contract', 'PaperlessBilling','PaymentMethod']# 連續(xù)字段 numeric_cols = ['MonthlyCharges', 'TotalCharges']# 標(biāo)簽 target = 'Churn'# 驗(yàn)證是否劃分能完全 assert len(category_cols) + len(numeric_cols) + 1 == tcc.shape[1]??當(dāng)然,大多數(shù)時(shí)候離散型字段都在讀取時(shí)都是object類型,因此我們也可以通過(guò)如下方式直接提取object字段:
tcc.select_dtypes('object').columns #Index(['customerID', 'gender', 'Partner', 'Dependents', 'PhoneService', # 'MultipleLines', 'InternetService', 'OnlineSecurity', 'OnlineBackup', # 'DeviceProtection', 'TechSupport', 'StreamingTV', 'StreamingMovies', # 'Contract', 'PaperlessBilling', 'PaymentMethod', 'TotalCharges', # 'Churn'], # dtype='object')然后,我們需要對(duì)不同類型字段進(jìn)行轉(zhuǎn)化。并且在此過(guò)程中,我們需要檢驗(yàn)是否存在采用別的值來(lái)表示缺失值的情況。就像此前所說(shuō)我們通過(guò)isnull只能檢驗(yàn)出None(Python原生對(duì)象)和np.Nan(numpy/pandas在讀取數(shù)據(jù)文件時(shí)文件內(nèi)部缺失對(duì)象的讀取后表示形式)對(duì)象。但此外我們還需要注意數(shù)據(jù)集中是否包含采用某符號(hào)表示缺失值的情況,例如某些時(shí)候可能使用空格(其本質(zhì)也是一種字符)來(lái)代替空格:
df = pd.DataFrame({'A':['Y', None, 'N', 'N'], 'B':[np.NaN, ' ', 'Y', 'N']}) df
此時(shí)在進(jìn)行檢驗(yàn)時(shí),空格的數(shù)據(jù)并不會(huì)被識(shí)別為缺失值(空格本身也是一種值)。
但根據(jù)實(shí)際情況來(lái)看,空格可能確實(shí)是代表著數(shù)據(jù)采集時(shí)數(shù)據(jù)是缺失的,因此我們?nèi)匀恍枰獙⑵渥R(shí)別然后標(biāo)記為缺失值,此時(shí)可以通過(guò)比較數(shù)據(jù)集各列的取值水平是否和既定的一致來(lái)進(jìn)行檢查。例如,對(duì)于上述df數(shù)據(jù)集來(lái)說(shuō),特征A和B默認(rèn)情況只有Y和N兩種取值,而B列由于通過(guò)空格表示了缺失值,因此用nunique查看數(shù)據(jù)集的話,B列將出現(xiàn)3種取值:
注意,缺失值None或NaN并不是某一種取值
此時(shí)我們可以進(jìn)一步查看B列每個(gè)不同取值出現(xiàn)的次數(shù):
df['B'].explode().value_counts().to_dict() #{'Y': 1, 'N': 1, ' ': 1}在判斷空格為缺失值后,我們即可對(duì)其進(jìn)行后續(xù)處理。我們可以先檢驗(yàn)離散變量是否存在這種情況:
tcc[category_cols].nunique() #customerID 7043 #gender 2 #SeniorCitizen 2 #Partner 2 #Dependents 2 #tenure 73 #PhoneService 2 #MultipleLines 3 #InternetService 3 #OnlineSecurity 3 #OnlineBackup 3 #DeviceProtection 3 #TechSupport 3 #StreamingTV 3 #StreamingMovies 3 #Contract 3 #PaperlessBilling 2 #PaymentMethod 4 #dtype: int64我們也可以通過(guò)如下方式查看每個(gè)離散變量的不同取值:
for feature in tcc[category_cols]:print(f'{feature}: {tcc[feature].unique()}') #customerID: ['7590-VHVEG' '5575-GNVDE' '3668-QPYBK' ... '4801-JZAZL' '8361-LTMKD' # '3186-AJIEK'] #gender: ['Female' 'Male'] #SeniorCitizen: [0 1] #Partner: ['Yes' 'No'] #Dependents: ['No' 'Yes'] #tenure: [ 1 34 2 45 8 22 10 28 62 13 16 58 49 25 69 52 71 21 12 30 47 72 17 27 # 5 46 11 70 63 43 15 60 18 66 9 3 31 50 64 56 7 42 35 48 29 65 38 68 # 32 55 37 36 41 6 4 33 67 23 57 61 14 20 53 40 59 24 44 19 54 51 26 0 # 39] #PhoneService: ['No' 'Yes'] #MultipleLines: ['No phone service' 'No' 'Yes'] #InternetService: ['DSL' 'Fiber optic' 'No'] #OnlineSecurity: ['No' 'Yes' 'No internet service'] #OnlineBackup: ['Yes' 'No' 'No internet service'] #DeviceProtection: ['No' 'Yes' 'No internet service'] #TechSupport: ['No' 'Yes' 'No internet service'] #StreamingTV: ['No' 'Yes' 'No internet service'] #StreamingMovies: ['No' 'Yes' 'No internet service'] #Contract: ['Month-to-month' 'One year' 'Two year'] #PaperlessBilling: ['Yes' 'No'] #PaymentMethod: ['Electronic check' 'Mailed check' 'Bank transfer (automatic)' # 'Credit card (automatic)']'''或者''' for feature in category_cols:print("{0}:{1}".format(feature,tcc[feature].unique()))通過(guò)對(duì)比離散變量的取值水平,我們發(fā)現(xiàn)并不存在通過(guò)其他值表示缺失值的情況。
需要注意的是,如果是連續(xù)變量,則無(wú)法使用上述方法進(jìn)行檢驗(yàn)(取值水平較多),但由于往往我們需要將其轉(zhuǎn)化為數(shù)值型變量再進(jìn)行分析,因此對(duì)于連續(xù)變量是否存在其他值表示缺失值的情況,我們也可以觀察轉(zhuǎn)化情況來(lái)判別,例如如果是用空格代表缺失值,則無(wú)法直接使用astype來(lái)轉(zhuǎn)化成數(shù)值類型。
# 無(wú)法全部轉(zhuǎn)化為數(shù)值型字段,運(yùn)行將報(bào)錯(cuò) # tcc[numeric_cols].astype(float)- 缺失值檢驗(yàn)與填補(bǔ)
發(fā)現(xiàn)在連續(xù)特征中存在空格。則此時(shí)我們需要進(jìn)一步檢查空格字符出現(xiàn)在哪一列的哪個(gè)位置,我們可以通過(guò)如下函數(shù)來(lái)進(jìn)行檢驗(yàn):
def find_index(data_col, val):"""查詢某值在某列中第一次出現(xiàn)位置的索引,沒(méi)有則返回-1:param data_col: 查詢的列:param val: 具體取值"""val_list = [val]if data_col.isin(val_list).sum() == 0:index = -1else:index = data_col.isin(val_list).idxmax()return index tcc["MonthlyCharges"].isin([" "]) #0 False #1 False #2 False #3 False #4 False # ... #7038 False #7039 False #7041 False #7042 False #Name: MonthlyCharges, Length: 7043, dtype: bool查看空格第一次出現(xiàn)在哪一列的哪個(gè)位置:
for col in numeric_cols:print(find_index(tcc[col], ' ')) #-1 #488即空格第一次出現(xiàn)在’TotalCharges’列的索引值為488的位置:
tcc['TotalCharges'].iloc[488] #' '接下來(lái)使用np.nan對(duì)空格進(jìn)行替換,并將’MonthlyCharges’轉(zhuǎn)化為浮點(diǎn)數(shù)類型:
tcc['TotalCharges']= tcc['TotalCharges'].apply(lambda x: x if x!= ' ' else np.nan).astype(float) tcc['MonthlyCharges'] = tcc['MonthlyCharges'].astype(float)再次查看連續(xù)變量的缺失值占比情況:
missing(tcc[numeric_cols])
關(guān)于該缺失值應(yīng)該如何填補(bǔ),首先考慮的是,由于缺失值占比較小,因此可以直接使用均值進(jìn)行填充:
此外,我們也可以簡(jiǎn)單觀察缺失’TotalCharges’信息的每條數(shù)據(jù)實(shí)際情況,或許能發(fā)現(xiàn)一些蛛絲馬跡:
tcc[tcc['TotalCharges'].isnull()]
我們發(fā)現(xiàn),這11條數(shù)據(jù)的入網(wǎng)時(shí)間都是0,也就是說(shuō),這11位用戶極有可能是在統(tǒng)計(jì)周期結(jié)束前的最后時(shí)間入網(wǎng)的用戶,因此沒(méi)有過(guò)去的總消費(fèi)記錄,但是卻有當(dāng)月的消費(fèi)記錄。也就是說(shuō),該數(shù)據(jù)集的過(guò)去總消費(fèi)記錄不包括當(dāng)月消費(fèi)記錄,也就是不存在過(guò)去總消費(fèi)記錄等于0的記錄。我們可以簡(jiǎn)單驗(yàn)證:
既然如此,我們就可以將這11條記錄的缺失值記錄為0,以表示在最后一個(gè)月統(tǒng)計(jì)消費(fèi)金額前,這些用戶的過(guò)去總消費(fèi)金額為0:
tcc['TotalCharges'] = tcc['TotalCharges'].fillna(0) tcc['TotalCharges'].isnull().sum() #0 tcc['TotalCharges'].describe() #count 7043.000000 #mean 2279.734304 #std 2266.794470 #min 0.000000 #25% 398.550000 #50% 1394.550000 #75% 3786.600000 #max 8684.800000 #Name: TotalCharges, dtype: float64此外還有另一種便捷的方式,即直接使用pd.to_numeric對(duì)連續(xù)變量進(jìn)行轉(zhuǎn)化,并在errors參數(shù)位上輸入’coerce’參數(shù),表示能直接轉(zhuǎn)化為數(shù)值類型時(shí)直接轉(zhuǎn)化,無(wú)法轉(zhuǎn)化的用缺失值填補(bǔ),過(guò)程如下:
df1 = pd.read_csv('WA_Fn-UseC_-Telco-Customer-Churn.csv') df1.TotalCharges = pd.to_numeric(df1.TotalCharges, errors='coerce') # 查看缺失值情況 df1.TotalCharges.isnull().sum() #11 # 查看原空格處是否被標(biāo)記為缺失值 df1.TotalCharges.iloc[488] #nan # 查看字段整體類型 df1.TotalCharges.dtype #dtype('float64')注意,此處暫時(shí)未對(duì)離散特征進(jìn)行變量類型轉(zhuǎn)化,是因?yàn)楸拘」?jié)后半段需要圍繞標(biāo)簽取值在不同特征維度上分布進(jìn)行分析,此時(shí)需要查看各特征的原始取值情況(例如性別是Male和Female,而不是0/1),因此我們會(huì)在本節(jié)結(jié)束后對(duì)離散變量再進(jìn)行字典編碼。
- 異常值檢驗(yàn)
??當(dāng)然,對(duì)于連續(xù)型變量,我們可以進(jìn)一步對(duì)其進(jìn)行異常值檢測(cè)。首先我們可以采用describe方法整體查看連續(xù)變量基本統(tǒng)計(jì)結(jié)果:
tcc[numeric_cols].describe()
異常值檢測(cè)有很多方法,我們可以通過(guò)三倍標(biāo)準(zhǔn)差法來(lái)進(jìn)行檢驗(yàn),即以均值-3倍標(biāo)注差為下界,均值+3倍標(biāo)準(zhǔn)差為上界,來(lái)檢測(cè)是否有超過(guò)邊界的點(diǎn):
能夠發(fā)現(xiàn),數(shù)據(jù)集并不存在異常值點(diǎn)。
??此外,我們還可以通過(guò)箱線圖來(lái)進(jìn)行異常值點(diǎn)的識(shí)別(數(shù)據(jù)偏態(tài)嚴(yán)重用箱線圖好,正態(tài)分布兩種方法都好),和3倍標(biāo)準(zhǔn)差法利用均值和方差進(jìn)行計(jì)算不同,箱線圖主要借助中位數(shù)和四分位數(shù)來(lái)進(jìn)行計(jì)算,以上四分位數(shù)+1.5倍四分位距為上界、下四分位數(shù)-1.5倍四分位距為下界,超出界限則認(rèn)為是異常值。我們可以借助plt.boxplot繪圖函數(shù)迅速繪制箱線圖來(lái)觀察異常值點(diǎn)情況:
import seaborn as sns import matplotlib.pyplot as plt # MonthlyCharges上四分位數(shù) Q3 = tcc[numeric_cols].describe()['MonthlyCharges']['75%'] Q3 #89.85 # MonthlyCharges下四分位數(shù) Q1 = tcc[numeric_cols].describe()['MonthlyCharges']['25%'] Q1 #35.5 #MonthlyCharges的四分位距 IQR = Q3 - Q1 IQR #54.349999999999994 # 異常值上界 Q3 + 1.5 * IQR #171.375 # 異常值下界 Q1 - 1.5 * IQR #-46.02499999999999 tcc['MonthlyCharges'].min(), tcc['MonthlyCharges'].max() #(18.25, 118.75)Q3 = tcc[numeric_cols].describe()['TotalCharges']['75%'] Q1 = tcc[numeric_cols].describe()['TotalCharges']['25%'] IQR = Q3 - Q1 (Q1 - 1.5 * IQR, Q3 + 1.5 * IQR) #(-4683.525, 8868.675) tcc['TotalCharges'].min(), tcc['TotalCharges'].max() #(0.0, 8684.8)??不過(guò)需要知道的是,由于數(shù)據(jù)集中沒(méi)有超出邊界的異常值點(diǎn),因此在實(shí)際繪制箱線圖時(shí),箱線圖的邊界會(huì)以數(shù)據(jù)集的極值為準(zhǔn):
plt.figure(figsize=(16, 6), dpi=200) plt.subplot(121) plt.boxplot(tcc['MonthlyCharges']) plt.xlabel('MonthlyCharges') plt.subplot(122) plt.boxplot(tcc['TotalCharges']) plt.xlabel('TotalCharges')
??能夠發(fā)現(xiàn),根據(jù)箱線圖的判別結(jié)果,數(shù)據(jù)并沒(méi)有異常值出現(xiàn)。當(dāng)然,此外我們還能通過(guò)連續(xù)變量的分布情況來(lái)觀察是否存在異常值:
當(dāng)然,通過(guò)上述圖像我們也能基本看出月消費(fèi)金額和總消費(fèi)金額的基本分布情況,對(duì)于大多數(shù)用戶來(lái)說(shuō)月消費(fèi)金額和總消費(fèi)金額都較小,而月消費(fèi)金額所出現(xiàn)的波動(dòng),極有可能是某些套餐的組合定價(jià)。
需要知道的是,對(duì)于異常值的檢測(cè)和處理也是需要根據(jù)實(shí)際數(shù)據(jù)分布和業(yè)務(wù)情況來(lái)判定,一般來(lái)說(shuō),數(shù)據(jù)分布越傾向于正態(tài)分布,則通過(guò)三倍標(biāo)準(zhǔn)差或者箱線圖檢測(cè)的異常值會(huì)更加準(zhǔn)確一些,此外,在很多時(shí)候,異常值或許是某類特殊用戶的標(biāo)識(shí),有的時(shí)候我們需要圍繞異常值進(jìn)行單獨(dú)分析,而不是簡(jiǎn)單的對(duì)其進(jìn)行修改。
對(duì)于異常值的修改,最通用的方法就是天花板蓋帽法
三、變量相關(guān)性探索分析與探索性分析
1.標(biāo)簽取值分布
??在基本完成數(shù)據(jù)探索與處理之后,接下來(lái)我們可以通過(guò)探索標(biāo)簽在不同特征上的分布,來(lái)初步探索哪些特征對(duì)標(biāo)簽取值影響較大。當(dāng)然,首先我們可以先查看標(biāo)簽字段的取值分布情況:
y = tcc['Churn'] print(f'Percentage of Churn: {round(y.value_counts(normalize=True)[1]*100,2)} % --> ({y.value_counts()[1]} customer)\nPercentage of customer did not churn: {round(y.value_counts(normalize=True)[0]*100,2)} % --> ({y.value_counts()[0]} customer)') #Percentage of Churn: 26.54 % --> (1869 customer) #Percentage of customer did not churn: 73.46 % --> (5174 customer)'''或者''' (tcc['Churn'][tcc['Churn']=='No'].count())/tcc['Churn'].count() #0.7346301292063041 (tcc['Churn'][tcc['Churn']=='Yes'].count())/tcc['Churn'].count() #0.2653698707936959也就是在總共7000余條數(shù)據(jù)中,流失用戶占比約為26%,整體來(lái)看標(biāo)簽取值并不均勻,但如果放到用戶流失這一實(shí)際業(yè)務(wù)背景中來(lái)探討,流失用戶比例占比26%已經(jīng)是非常高的情況了。當(dāng)然我們也可以通過(guò)直方圖進(jìn)行直觀的觀察:
sns.displot(y) #sns.countplot(y) #sns.histplot(y)2.變量相關(guān)性分析
??接下來(lái),我們嘗試對(duì)變量和標(biāo)簽進(jìn)行相關(guān)性分析。從嚴(yán)格的統(tǒng)計(jì)學(xué)意義講,不同類型變量的相關(guān)性需要采用不同的分析方法,例如連續(xù)變量之間相關(guān)性可以使用皮爾遜相關(guān)系數(shù)進(jìn)行計(jì)算,而連續(xù)變量和離散變量之間相關(guān)性則可以卡方檢驗(yàn)進(jìn)行分析,而離散變量之間則可以從信息增益角度入手進(jìn)行分析。但是,如果我們只是想初步探查變量之間是否存在相關(guān)關(guān)系,則可以忽略變量連續(xù)/離散特性,統(tǒng)一使用相關(guān)系數(shù)進(jìn)行計(jì)算,這也是pandas中的.corr方法所采用的策略。
- 計(jì)算相關(guān)系數(shù)矩陣
??當(dāng)然,首先我們可以先計(jì)算相關(guān)系數(shù)矩陣,直接通過(guò)具體數(shù)值大小來(lái)表示相關(guān)性強(qiáng)弱。不過(guò)需要注意的是,盡管我們可以忽略變量的連續(xù)/離散特性,但為了更好的分析分類變量如何影響標(biāo)簽的取值,我們需要將標(biāo)簽轉(zhuǎn)化為整型(也就是視作連續(xù)變量),而將所有的分類變量進(jìn)行啞變量處理:
# 剔除ID列 df3 = tcc.iloc[:,1:].copy()# 將標(biāo)簽Yes/No轉(zhuǎn)化為1/0 df3['Churn'].replace(to_replace='Yes', value=1, inplace=True) df3['Churn'].replace(to_replace='No', value=0, inplace=True)# 將其他所有分類變量轉(zhuǎn)化為啞變量,連續(xù)變量保留不變 df_dummies = pd.get_dummies(df3) df_dummies.head()
此處需要注意pd.get_dummies會(huì)將非數(shù)值類型對(duì)象類型進(jìn)行自動(dòng)啞變量轉(zhuǎn)化,而對(duì)數(shù)值類型對(duì)象,無(wú)論是整型還是浮點(diǎn)型,都會(huì)保留原始列不變:
然后即可采用.corr方法計(jì)算相關(guān)系數(shù)矩陣:
當(dāng)然,在所有的相關(guān)性中,我們較為關(guān)注特征和標(biāo)簽之間的相關(guān)關(guān)系,因此可以直接挑選標(biāo)簽列的相關(guān)系數(shù)計(jì)算結(jié)果,并進(jìn)行降序排序:
df_dummies.corr()['Churn'].sort_values(ascending = False) # Churn 1.000000 # Contract_Month-to-month 0.405103 # OnlineSecurity_No 0.342637 # TechSupport_No 0.337281 # InternetService_Fiber optic 0.308020 # . . . # StreamingTV_No internet service -0.227890 # TechSupport_No internet service -0.227890 # OnlineBackup_No internet service -0.227890 # Contract_Two year -0.302253 # tenure -0.352229需要知道的是,根據(jù)相關(guān)系數(shù)計(jì)算的基本原理,相關(guān)系數(shù)為正數(shù),則二者為正相關(guān),數(shù)值變化會(huì)更傾向于保持同步。例如Churn與Contract_Month-to-month相關(guān)系數(shù)為0.4,則說(shuō)明二者存在一定的正相關(guān)性,即Contract_Month-to-month取值為1(更大)越有可能使得Churn取值為1。也就是在Contract字段的Month-to-month取值結(jié)果和最終流失的結(jié)果相關(guān)性較大,也就是相比其他條件,Contract取值為Month-to-month的用戶流失概率較大,而tenure和Churn負(fù)相關(guān),則說(shuō)明tenure取值越大、用戶流失概率越小。其他結(jié)果解讀依此類推。
- 熱力圖展示相關(guān)性
??當(dāng)然,我們也可以通過(guò)一些可視化的方式來(lái)展示特征和標(biāo)簽之間的相關(guān)性,例如可以考慮使用熱力圖進(jìn)行相關(guān)性的可視化展示:
plt.figure(figsize=(15,8), dpi=200) sns.heatmap (df_dummies.corr())- 柱狀圖展示相關(guān)性
??當(dāng)然,很多時(shí)候如果特征較多,熱力圖的展示結(jié)果并不直觀,此時(shí)我們可以考慮進(jìn)一步使用柱狀圖來(lái)進(jìn)行表示:
sns.set() plt.figure(figsize=(15,8), dpi=200)df_dummies.corr()['Churn'].sort_values(ascending = False).plot(kind='bar')3.探索性數(shù)據(jù)分析
??當(dāng)然,直接計(jì)算整體相關(guān)系數(shù)矩陣以及對(duì)整體相關(guān)性進(jìn)行可視化展示是一種非常高效便捷的方式,在實(shí)際的算法競(jìng)賽中,我們也往往會(huì)采用上述方法快速的完成數(shù)據(jù)相關(guān)性檢驗(yàn)和探索工作。不過(guò),如果是對(duì)于業(yè)務(wù)分析人員,可能我們需要為其展示更為直觀和具體的一些結(jié)果,才能有效幫助業(yè)務(wù)人員對(duì)相關(guān)性進(jìn)行判別。此時(shí)我們可以考慮圍繞不同類型的屬性進(jìn)行柱狀圖的展示與分析。當(dāng)然,此處需要對(duì)比不同字段不同取值下流失用戶的占比情況,因此可以考慮使用柱狀圖的另一種變形:堆疊柱狀圖來(lái)進(jìn)行可視化展示:
fig,axes=plt.subplots(nrows=1,ncols=2,figsize=(12,6), dpi=100)# 柱狀圖 plt.subplot(121) sns.countplot(x="gender",hue="Churn",data=tcc,palette="Blues", dodge=True) plt.xlabel("Gender") plt.title("Churn by Gender")# 柱狀堆疊圖 plt.subplot(122) sns.countplot(x="gender",hue="Churn",data=tcc,palette="Blues", dodge=False) plt.xlabel("Gender") plt.title("Churn by Gender")#x: x軸上的條形圖,以x標(biāo)簽劃分統(tǒng)計(jì)個(gè)數(shù) #y: y軸上的條形圖,以y標(biāo)簽劃分統(tǒng)計(jì)個(gè)數(shù) #hue: 在x或y標(biāo)簽劃分的同時(shí),再以hue標(biāo)簽劃分統(tǒng)計(jì)個(gè)數(shù)注,此處堆疊圖簡(jiǎn)單理解其實(shí)就是純粹的重合,并不是上下堆疊,而是深色柱狀圖覆蓋在淺色柱狀圖的上面。
接下來(lái),我們將根據(jù)此前劃分的字段類型來(lái)進(jìn)行逐類分析:
- 用戶人口統(tǒng)計(jì)信息
首先是用戶的人口統(tǒng)計(jì)信息:
col_1 = ["gender", "SeniorCitizen", "Partner", "Dependents"]fig,axes=plt.subplots(nrows=2,ncols=2,figsize=(16,12), dpi=200)for i, item in enumerate(col_1):plt.subplot(2,2,(i+1))ax=sns.countplot(x=item,hue="Churn",data=tcc,palette="Blues", dodge=False)plt.xlabel(item)plt.title("Churn by "+ item)
能夠發(fā)現(xiàn),老年用戶、未結(jié)婚用戶以及經(jīng)濟(jì)未獨(dú)立用戶流失比例相對(duì)較高,而性別因素對(duì)是否流失影響不大。在實(shí)際制定運(yùn)營(yíng)策略時(shí),這三類用戶需要重點(diǎn)關(guān)注。
- 已注冊(cè)的服務(wù)信息
??然后繼續(xù)分析服務(wù)屬性字段與用戶流失之間的關(guān)系:
col_2 = ["OnlineSecurity", "OnlineBackup", "DeviceProtection", "TechSupport", "StreamingTV", "StreamingMovies"]fig,axes=plt.subplots(nrows=2,ncols=3,figsize=(16,12))for i, item in enumerate(col_2):plt.subplot(2,3,(i+1))ax=sns.countplot(x=item,hue="Churn",data=tcc,palette="Blues",order=["Yes","No","No internet service"], dodge=False)plt.xlabel(item)plt.title("Churn by "+ item)
能夠發(fā)現(xiàn),未開通網(wǎng)絡(luò)服務(wù)的用戶、以及開通了網(wǎng)絡(luò)服務(wù)并且同時(shí)開通很多增值服務(wù)的用戶往往流失概率較小,而開通網(wǎng)絡(luò)服務(wù)、未開通其他增值服務(wù)的用戶流失概率較大。因此可以考慮更多的提供免費(fèi)體驗(yàn)增值服務(wù)的機(jī)會(huì),增加增值服務(wù)宣傳,促進(jìn)用戶購(gòu)買,從而提升用戶粘性。
- 用戶合同屬性
??接下來(lái)進(jìn)一步分析用戶合同屬性與流失率之間的關(guān)系:
col_3 = ["Contract", "PaperlessBilling", "PaymentMethod"]fig,axes=plt.subplots(nrows=2,ncols=2,figsize=(16,12))for i, item in enumerate(col_3):plt.subplot(2,2,(i+1))ax=sns.countplot(x=item,hue="Churn",data=tcc,palette="Blues", dodge=False)plt.xlabel(item)plt.title("Churn by "+ item)
能夠發(fā)現(xiàn),一次性簽署服務(wù)周期越短的用戶越容易流失,并且相比其他支付方式,在線支付的用戶更容易流失。因此可能需要在實(shí)際運(yùn)營(yíng)過(guò)程中更多的引導(dǎo)用戶簽訂長(zhǎng)期合同,無(wú)論是通過(guò)折扣還是滿贈(zèng),借此提升用戶生命周期。此外,需要更加關(guān)注在線支付用戶的實(shí)際產(chǎn)品體驗(yàn),也可以考慮提升在線支付本身的用戶體驗(yàn)或者提供更多的價(jià)格優(yōu)惠,以此提升在線支付用戶滿意度。
??當(dāng)然,如果能獲取更多的實(shí)際業(yè)務(wù)背景知識(shí),則能夠進(jìn)行更加深入的數(shù)據(jù)分析與用戶挽留策略的制定。不過(guò)需要知道的是,無(wú)論是作為實(shí)際建模預(yù)測(cè)項(xiàng)目,還是結(jié)合實(shí)際業(yè)務(wù)進(jìn)行數(shù)據(jù)分析,在完成數(shù)據(jù)清洗后對(duì)變量進(jìn)行相關(guān)性分析,都是了解數(shù)據(jù)情況的重要手段,也是所有建模過(guò)程中必備的環(huán)節(jié)。在后續(xù)的內(nèi)容中,我們也將在此基礎(chǔ)上進(jìn)一步來(lái)進(jìn)行特征工程以及模型訓(xùn)練的相關(guān)工作,最終借助模型,來(lái)進(jìn)行實(shí)時(shí)的用戶流失預(yù)測(cè),并且根據(jù)最終的模型結(jié)果來(lái)更精確的判別變量重要性,以及根據(jù)模型方程來(lái)判斷變量影響流失概率的量化結(jié)果。
總結(jié)
以上是生活随笔為你收集整理的电信用户流失预测案例(1)的全部?jī)?nèi)容,希望文章能夠幫你解決所遇到的問(wèn)題。
- 上一篇: 文章/网站分享工具——百度分享
- 下一篇: ionic4学习笔记11-某东项目热门商