1、数据理解

导入数据集文件、查看数据集前5条信息,查看数据集大小和摘要信息。

df = pd.read_csv('../input/telco-customer-churn/WA_Fn-UseC_-Telco-Customer-Churn.csv')
df.head()
df.shape
#执行df.shape会返回一个元组,该元组的第一个元素代表行数,第二个元素代表列数,这就是这个数据的基本形状,也是数据的大小
df.info()
#Pandas dataframe.info()函数用于获取 DataFrame 的简要摘要。在对数据进行探索性分析时,它非常方便。为了快速浏览数据集,我们使用dataframe.info()功能。

  

电信公司数据分析项目代码实现 电信数据分析入门_Internet

 

电信公司数据分析项目代码实现 电信数据分析入门_数据_02

 

电信公司数据分析项目代码实现 电信数据分析入门_电信公司数据分析项目代码实现_03

 

2、数据清洗

msno.matrix(df);
## 将缺失值可视化为矩阵,发现无缺失值
# 无效数据密度显示,若是图中白线越多,则说明缺失值越多。左侧纵坐标上的两个数值为样本数量的始末(即从 1 开始数有 506 条数据),右下角数字 12 表示数据中共有 12 列不存在缺失值,右侧数字 14 表示数据共计 14 列。\

电信公司数据分析项目代码实现 电信数据分析入门_Internet_04

 

 

 

df = df.drop(['customerID'], axis = 1)
df.head()
#删除没用的列,再次查看前五行
#删除表中的某一行或者某一列更明智的方法是使用drop,它不改变原有的df中的数据,而是返回另一个dataframe来存放删除后的数据。
#drop函数默认删除行,列需要加axis = 1

电信公司数据分析项目代码实现 电信数据分析入门_缺失值_05

 

 

 

df['TotalCharges'] = pd.to_numeric(df.TotalCharges, errors='coerce')
df.isnull().sum()
# 类型转换1,将‘TotalCharges’总消费额的数据类型转换为数字类型,统计每列缺失值的个数,有11个缺失值
#arg : scalar(标量),list(列表),(tuple)元组,一维数组(1-d array)或Series
#errors  : {'ignore','raise','coerce'},默认为'raise'如果为‘raise’,则无效的解析将引发异常如果为 ‘coerce’,则将无效解析设置为NaN如果为 ‘ignore’,则无效的解析将返回输入

电信公司数据分析项目代码实现 电信数据分析入门_Internet_06

 

 

 

df[np.isnan(df['TotalCharges'])]
#查看这11行带有缺失值的数据,发现这11个用户‘tenure’(入网时长)为0个月

电信公司数据分析项目代码实现 电信数据分析入门_数据_07

 

 

 

df[df['tenure'] == 0].index
#查看tenure为0的索引,看是否有其他月费存在但是入网时间为0的用户,发现没有

电信公司数据分析项目代码实现 电信数据分析入门_Internet_08

 

 

df.drop(labels=df[df['tenure'] == 0].index, axis=0, inplace=True)
df[df['tenure'] == 0].index
#删除标签为表格中tenure=0对应的11行,对数据影响不大,并改变表格,
#labels:一个字符或者数值,加上axis ,表示带label标识的行或者列;如 (labels='A', axis=1) 表示A列
#axis:axis=0表示行,axis=1表示列
#columns:列名
#index:表示dataframe的index, 如index=1, index=a
#inplace:True表示删除某行后原dataframe变化,False不改变原始dataframe

电信公司数据分析项目代码实现 电信数据分析入门_电信公司数据分析项目代码实现_09

 

 

df["SeniorCitizen"]= df["SeniorCitizen"].map({0: "No", 1: "Yes"})
df.head()
#类型转换2,把seniorcitizen数据类型转换为字符型,替换列值使用字典进行映射

  

电信公司数据分析项目代码实现 电信数据分析入门_Internet_10

 

 

 

 

df.isnull().sum()
#再次查看缺失值,无缺失

 

电信公司数据分析项目代码实现 电信数据分析入门_电信公司数据分析项目代码实现_11

 

 

numerical_cols = ['tenure', 'MonthlyCharges', 'TotalCharges']
df[numerical_cols].describe()
#获取数据类型的描述统计信息,根据一般经验,所有数据正常。

 

电信公司数据分析项目代码实现 电信数据分析入门_电信公司数据分析项目代码实现_12

3、数据可视化

#客户流失饼状图
plt.pie(df["Churn"].value_counts(), labels=df["Churn"].value_counts().index, explode=(0.1, 0), autopct='%1.2f%%', shadow=True, colors = ['#c2c2f0','#ffb3e6', '#66b3ff'])
plt.title("客户流失比例")
plt.show()
#属于不平衡数据

 

电信公司数据分析项目代码实现 电信数据分析入门_电信公司数据分析项目代码实现_13

 

 

3.1用户分析

#分别查看老年人和性别对客户流失的影响
def barplot_percentages(feature,orient='v',axis_name="percentage of customers"):
    ratios = pd.DataFrame()
    g = (df.groupby(feature)["Churn"].value_counts()/len(df)).to_frame()
    g.rename(columns={"Churn":axis_name},inplace=True)
    g.reset_index(inplace=True)
 
    #print(g)
    if orient == 'v':
        ax = sns.barplot(x=feature, y= axis_name, hue='Churn', data=g, orient=orient)
        ax.set_yticklabels(['{:,.0%}'.format(y) for y in ax.get_yticks()])
        plt.rcParams.update({'font.size': 13})
        #plt.legend(fontsize=10)
    else:
        ax = sns.barplot(x= axis_name, y=feature, hue='Churn', data=g, orient=orient)
        ax.set_xticklabels(['{:,.0%}'.format(x) for x in ax.get_xticks()])
        plt.legend(fontsize=10)
    plt.title('Churn(Yes/No) Ratio as {0}'.format(feature))
    plt.show()
barplot_percentages("SeniorCitizen")
barplot_percentages("gender")

 

电信公司数据分析项目代码实现 电信数据分析入门_缺失值_14

 

 

 

电信公司数据分析项目代码实现 电信数据分析入门_电信公司数据分析项目代码实现_15

 

 

 

 

#进一步观察性别、老年用户与流失的关系
df['churn_rate'] = df['Churn'].replace("No", 0).replace("Yes", 1)
g = sns.FacetGrid(df, col="SeniorCitizen", height=4, aspect=.9)
ax = g.map(sns.barplot, "gender", "churn_rate", palette = "Blues_d", order= ['Female', 'Male'])
plt.rcParams.update({'font.size': 13})
plt.show()
#用户流失与性别基本无关;年老用户流失占显著高于年轻用户。

电信公司数据分析项目代码实现 电信数据分析入门_Internet_16

 

 

 

#观察家属、配偶与用户流失的关系
fig, axis = plt.subplots(1, 2, figsize=(12,4))
axis[0].set_title("Has Partner")
axis[1].set_title("Has Dependents")
axis_y = "percentage of customers"
 
# Plot Partner column
gp_partner = (df.groupby('Partner')["Churn"].value_counts()/len(df)).to_frame()
gp_partner.rename(columns={"Churn": axis_y}, inplace=True)
gp_partner.reset_index(inplace=True)
ax1 = sns.barplot(x='Partner', y= axis_y, hue='Churn', data=gp_partner, ax=axis[0])
ax1.legend(fontsize=10)
#ax1.set_xlabel('伴侣')
 
 
# Plot Dependents column
gp_dep = (df.groupby('Dependents')["Churn"].value_counts()/len(df)).to_frame()
#print(gp_dep)
gp_dep.rename(columns={"Churn": axis_y} , inplace=True)
#print(gp_dep)
gp_dep.reset_index(inplace=True)
#print(gp_dep)
 
ax2 = sns.barplot(x='Dependents', y= axis_y, hue='Churn', data=gp_dep, ax=axis[1])
#ax2.set_xlabel('家属')
 
 
#设置字体大小
plt.rcParams.update({'font.size': 20})
ax2.legend(fontsize=10)
 
#设置
plt.show()
#发现有伴侣的用户流失占比低于无伴侣用户
有家属的用户流失占比低于无家属用户

  

电信公司数据分析项目代码实现 电信数据分析入门_Internet_17

 

 

 

 

 

# Kernel density estimaton核密度估计观察入网时间与流失关系
def kdeplot(feature,xlabel):
    plt.figure(figsize=(9, 4))
    plt.title("KDE for {0}".format(feature))
    ax0 = sns.kdeplot(df[df['Churn'] == 'No'][feature].dropna(), color= 'navy', label= 'Churn: No', shade='True')
    ax1 = sns.kdeplot(df[df['Churn'] == 'Yes'][feature].dropna(), color= 'orange', label= 'Churn: Yes',shade='True')
    plt.xlabel(xlabel)
    #设置字体大小
    plt.rcParams.update({'font.size': 20})
    plt.legend(fontsize=10)
kdeplot('tenure','tenure')
plt.show()
#发现新用户比较容易流失

  

电信公司数据分析项目代码实现 电信数据分析入门_缺失值_18

 

 

 

 

3.2产品分析

#电话服务和多线对用户流失影响较小
plt.figure(figsize=(9, 4.5))
barplot_percentages("MultipleLines", orient='h')

  

电信公司数据分析项目代码实现 电信数据分析入门_Internet_19

 

 

 

#单光纤用户流失占比较高
plt.figure(figsize=(9, 4.5))
barplot_percentages("InternetService", orient="h")

  

电信公司数据分析项目代码实现 电信数据分析入门_缺失值_20

 

 

 

#订阅“在线安全”、“在线备份”、“设备保护”和“技术支持”的流失率较低
cols = ["PhoneService","MultipleLines","OnlineSecurity", "OnlineBackup", "DeviceProtection", "TechSupport", "StreamingTV", "StreamingMovies"]
df1 = pd.melt(df[df["InternetService"] != "No"][cols])
df1.rename(columns={'value': 'Has service'},inplace=True)
plt.figure(figsize=(20, 8))
ax = sns.countplot(data=df1, x='variable', hue='Has service')
ax.set(xlabel='Internet Additional service', ylabel='Num of customers')
plt.rcParams.update({'font.size':20})
plt.legend( labels = ['No Service', 'Has Service'],fontsize=15)
plt.title('Num of Customers as Internet Additional Service')
plt.show()

  

电信公司数据分析项目代码实现 电信数据分析入门_缺失值_21

 

 

 

#流媒体电视、电影服务与用户流失无关
plt.figure(figsize=(20, 8))
df1 = df[(df.InternetService != "No") & (df.Churn == "Yes")]
df1 = pd.melt(df1[cols])
df1.rename(columns={'value': 'Has service'}, inplace=True)
ax = sns.countplot(data=df1, x='variable', hue='Has service', hue_order=['No', 'Yes'])
ax.set(xlabel='Internet Additional service', ylabel='Churn Num')
plt.rcParams.update({'font.size':20})
plt.legend( labels = ['No Service', 'Has Service'],fontsize=15)
plt.title('Num of Churn Customers as Internet Additional Service')
plt.show()

  

电信公司数据分析项目代码实现 电信数据分析入门_缺失值_22

 

 

 

3.3用户行为分析

#支付方式与流失
plt.figure(figsize=(9, 4.5))
barplot_percentages("PaymentMethod",orient='h')
#电子支付更容易流失客户。

  

电信公司数据分析项目代码实现 电信数据分析入门_电信公司数据分析项目代码实现_23

 

 

 

#无纸化账单与流失
g = sns.FacetGrid(df, col="PaperlessBilling", height=6, aspect=.9)
ax = g.map(sns.barplot, "Contract", "churn_rate", palette = "Blues_d", order= ['Month-to-month', 'One year', 'Two year'])
plt.rcParams.update({'font.size':18})
plt.show()
#无纸化账单的客户更容易流失。

  

 

电信公司数据分析项目代码实现 电信数据分析入门_数据_24

 

 

 

#月费与流失,总费与流失
kdeplot('MonthlyCharges','MonthlyCharges')
kdeplot('TotalCharges','TotalCharges')
plt.show()
#月费率越高越容易流失客户,总费用少的用户容易流失

  

电信公司数据分析项目代码实现 电信数据分析入门_数据_25

 

 

 

电信公司数据分析项目代码实现 电信数据分析入门_缺失值_26

 

 

 3.4总结

(1)用户流失与性别gender无关。

(2)老年人流失比率比较大,原因可能在于老年人对电信套餐认识不深,普及度较低,容易流失老年人客户。

(3)没有伴侣以及没有家属的用户流失率大。伴侣及家庭成员的存在可以显著影响电信用户的留存或流失。

(4)用户流失基本与手机服务指标“电话服务”和“多线”无关。可能是因为这是电信企业的核心业务,用户流失与此无关。

(5)网络服务指标中,采用光纤服务的用户更容易流失。可能是因为光纤服务的性价比不高。

(6)其他订阅服务指标中,前四项服务(“在线安全”、“在线备份”、“设备保护”和“技术支持”)对客户流失呈正相关,没有订阅该服务的用户较容易流失,后两项(“流媒体电视”和“流媒体电影”)对客户流失没有明显关系。

(7)电子支付更容易流失客户。可能是因为办理业务方便,抑或是操作频率高,使客户厌倦。

(8)采用无纸化账单的客户更容易流失。可能是因为让客户的钱流动没有感觉。

(9)合同签约期越长用户越不容易流失。2年合同若在中途毁约,对客户有一定损失,这在一定程度上减少了客户的流失。

(10)新客户更容易流失。可以采取一定的折扣方案挽留新用户,提高新用户的留存率。

(11)月费率越高越容易流失客户,若不在高费率的基础上提供更优质的服务,容易导致用户流失。月费为60元左右可以使得流失率较低且留存率较高,此后流失率大幅增加。80元左右时,客户的流失率达到顶峰。

(12)总费用少的用户反而容易流失。因此费用保持在60元左右最好。

电信公司数据分析项目代码实现 电信数据分析入门_缺失值_27

 

 

3.5建议

(1)用户方面:针对老年用户、无亲属、无伴侣用户的特征推出定制服务如老年朋友套餐、温暖套餐等。鼓励用户加强关联,推出各种亲子套餐、情侣套餐等,满足客户的多样化需求。针对新注册用户,推送半年优惠如赠送消费券,以度过用户流失高峰期。

(2)产品方面:针对光纤用户可以推出光纤和通讯组合套餐,对于连续开通半年以上的用户给与优惠减免。开通网络电视、电影的用户容易流失,需要研究这些用户的流失原因,是服务体验如观影流畅度清晰度等不好还是资源如片源等过少,再针对性的解决问题。针对在线安全、在线备份、设备保护、技术支持等增值服务,应重点对用户进行推广介绍,如首月/半年免费体验,使客户习惯并受益于这些服务。

(3)用户行为方面:针对单月合同用户,建议推出年合同付费折扣活动,将月合同用户转化为年合同用户,提高用户存留时长,以减少用户流失。 针对采用电子支票支付用户,建议定向推送其它支付方式的优惠券,引导用户改变支付方式。对于开通电子账单的客户,可以在电子账单上增加等级积分等显示,等级升高可以免费享受增值服务,积分可以兑换某些日用商品。