<jupyter_start><jupyter_text>ML-Final Project<jupyter_code>#Importing libraries
import numpy as np # linear algebra
import pandas as pd # data processing, CSV file I/O (e.g. pd.read_csv)
# Input data files are available in the "../input/" directory.
import os
import matplotlib.pyplot as plt#visualization
from PIL import  Image
%matplotlib inline
import pandas as pd
import seaborn as sns#visualization
import itertools
import warnings
warnings.filterwarnings("ignore")
import io
import matplotlib.ticker as mtick # For specifying the axes tick format 
import matplotlib.pyplot as plt#visualization
import plotly.offline as py#visualization
py.init_notebook_mode(connected=True)#visualization
import plotly.graph_objs as go#visualization
import plotly.tools as tls#visualization
import plotly.figure_factory as ff#visualization<jupyter_output><empty_output><jupyter_text>Read the csv file and store it in df<jupyter_code>df = pd.read_csv("ML-Final-project.csv")<jupyter_output><empty_output><jupyter_text>Data Information Customer attrition, also known as customer churn, customer turnover, or customer defection, is the loss of clients or customers.Customer churn is a key metric for businesses. Service based industries like subscription based TV companies, telecommunication companies, internet service providers, insurance companies benefit from analysing their customer data to identify important features that may be attributed to customers leaving the service. The customer-relationship management departments of companies handle customer retention and defection as maintaining a pre-existing customer or recovering a former customer is more cost efficient, as opposed to obtaining new clients. The distinction between voluntary and involuntary customer churn is often defined by the companies. Customers who switch voluntarily to another service fall under the voluntary churn category, whereas the customer who switch due to relocation are often involuntary and fall under the involuntary churn category. Companies focus on voluntary churn as they have more control on their customer interactions. Churn prediction falls under predictive analytics which assess customer interaction with the company and find their churn risk.  Retention marketing programs focus on the customers who have high risk of churn using these analytics.Customer churn occurs when customers or subscribers stop doing business with a company or service. Also known as customer attrition, customer churn is a critical metric because it is much less expensive to retain existing customers than it is to acquire new customers – earning business from new customers means working leads all the way through the sales funnel, utilizing your marketing and sales resources throughout the process. Customer retention, on the other hand, is generally more cost-effective, as you have already earned the trust and loyalty of existing customers.[Dataset](https://www.kaggle.com/blastchar/telco-customer-churn)  The data set includes information about:- Customers who left within the last month – the column is called Churn- Services that each customer has signed up for – phone, multiple lines, internet, online security, online backup, device protection, tech support, and streaming TV and movies- Customer account information – how long they’ve been a customer, contract, payment method, paperless billing, monthly charges, and total charges- Demographic info about customers – gender, age range, and if they have partners and dependents  The data set columns are as following:- customerID : Unique Id for customers- gender : Whether the customer is a male or a female- SeniorCitizen : Whether the customer is a senior citizen or not (1, 0)- Partner : Whether the customer has a partner or not (Yes, No)- Dependents : Whether the customer has dependents or not (Yes, No)- tenure : Number of months the customer has stayed with the company- PhoneService : Whether the customer has a phone service or not (Yes, No)- MultipleLines : Whether the customer has multiple lines or not (Yes, No, No phone service)- InternetService : Customer’s internet service provider (DSL, Fiber optic, No)- OnlineSecurity : Whether the customer has online security or not (Yes, No, No internet service)- OnlineBackup : Whether the customer has online backup or not (Yes, No, No internet service)- DeviceProtection : Whether the customer has device protection or not (Yes, No, No internet service)- TechSupport : Whether the customer has tech support or not (Yes, No, No internet service)- StreamingTV : Whether the customer has streaming TV or not (Yes, No, No internet service)- StreamingMovies : Whether the customer has streaming movies or not (Yes, No, No internet service)- Contract : The contract term of the customer (Month-to-month, One year, Two year)- PaperlessBilling : Whether the customer has paperless billing or not (Yes, No)- PaymentMethod : The customer’s payment method (Electronic check, Mailed check, Bank transfer (automatic), Credit card (automatic))- MonthlyCharges : The amount charged to the customer monthly- TotalCharges : The total amount charged to the customer- Churn : Whether the customer churned or not (Yes or No)<jupyter_code>df.head()
df.info()<jupyter_output><class 'pandas.core.frame.DataFrame'>
RangeIndex: 7043 entries, 0 to 7042
Data columns (total 21 columns):
customerID          7043 non-null object
gender              7043 non-null object
SeniorCitizen       7043 non-null int64
Partner             7043 non-null object
Dependents          7043 non-null object
tenure              7043 non-null int64
PhoneService        7043 non-null object
MultipleLines       7043 non-null object
InternetService     7043 non-null object
OnlineSecurity      7043 non-null object
OnlineBackup        7043 non-null object
DeviceProtection    7043 non-null object
TechSupport         7043 non-null object
StreamingTV         7043 non-null object
StreamingMovies     7043 non-null object
Contract            7043 non-null object
PaperlessBilling    7043 non-null object
PaymentMethod       7043 non-null object
MonthlyCharges      7043 non-null float64
TotalCharges        7043 non-null object
Churn               7043 non-null object
dtypes: float64(1), int64(2), obj[...]<jupyter_text>Data Preprocessing  Since the TotalCharges is an object, we need to convert it to a numeric value<jupyter_code>df.TotalCharges = pd.to_numeric(df.TotalCharges, errors='coerce')<jupyter_output><empty_output><jupyter_text>Checking for null values now<jupyter_code>df.isnull().sum()<jupyter_output><empty_output><jupyter_text>Since there are only 11 rows with null values, we will drop these rows from the dataframe<jupyter_code># Ksh

df = df.dropna()
df.isnull().sum()
#Data Manipulation

#replace 'No internet service' to No for the following columns
replace_cols = [ 'OnlineSecurity', 'OnlineBackup', 'DeviceProtection',
                'TechSupport','StreamingTV', 'StreamingMovies']
for i in replace_cols : 
    df[i]  = df[i].replace({'No internet service' : 'No'})
    
#replace values
df["SeniorCitizen"] = df["SeniorCitizen"].replace({1:"Yes",0:"No"})

#Tenure to categorical column
def tenure_lab(df) :
    if df["tenure"] <= 6 :
        return "Months_1-6"
    elif (df["tenure"] > 6) & (df["tenure"] <= 12 ):
        return "Months_7-12"
    elif (df["tenure"] > 12) & (df["tenure"] <= 18) :
        return "Months_13-18"
    elif (df["tenure"] > 18) & (df["tenure"] <= 24) :
        return "Months_19-24"
    elif (df["tenure"] > 24) & (df["tenure"] <= 36) :
        return "Months_24-36"
    elif (df["tenure"] > 36) & (df["tenure"] <= 48) :
        return "Months_36-48"
    elif (df["tenure"] > 48) & (df["tenure"] <= 60) :
        return "Months_48-60"
    elif (df["tenure"] > 60) :
        return "Months_60+"
df["tenure_group"] = df.apply(lambda df:tenure_lab(df),
                                      axis = 1)

#Separating churn and non churn customers
churn     = df[df["Churn"] == "Yes"]
not_churn = df[df["Churn"] == "No"]

#Separating catagorical and numerical columns
Id_col     = ['customerID']
target_col = ["Churn"]
cat_cols   = df.nunique()[df.nunique() < 6].keys().tolist()
cat_cols   = [x for x in cat_cols if x not in target_col]
num_cols   = [x for x in df.columns if x not in cat_cols + target_col + Id_col]

df.head()<jupyter_output><empty_output><jupyter_text>Visualization<jupyter_code>ax = (df['gender'].value_counts() /70.32).plot(kind='bar',stacked = True,rot = 0,color = ['#0000FF','#FFC0CB'])
ax.yaxis.set_major_formatter(mtick.PercentFormatter())
ax.set_title('Gender Distribution of Customers')
ax.set_xlabel('Gender of Customers')
ax.set_ylabel('Percentage of Customers')



# create a list to collect the plt.patches data
totals = []

# # find the values and append to list
for i in ax.patches:
    print(i)
    totals.append(i.get_width())

# set individual bar lables using above list
total = sum(totals)

for i in ax.patches:
    # get_width pulls left or right; get_y pushes up or down
    ax.text(i.get_x()+.15, i.get_height()-3.5, \
            str(round((i.get_height()/total), 1))+'%',fontsize=12,color='white',weight = 'bold')

#labels
lab = df["Churn"].value_counts().keys().tolist()
#values
val = df["Churn"].value_counts().values.tolist()

trace = go.Pie(labels = lab ,
               values = val ,
               marker = dict(colors =  [ 'royalblue' ,'lime'],
                             line = dict(color = "white",
                                         width =  1.3)
                            ),
               rotation = 90,
               hoverinfo = "label+value+text",
               hole = .5
              )
layout = go.Layout(dict(title = "Customer attrition in data",
                        plot_bgcolor  = "rgb(243,243,243)",
                        paper_bgcolor = "rgb(243,243,243)",
                       )
                  )

data = [trace]
fig = go.Figure(data = data,layout = layout)
py.iplot(fig)
#cusomer attrition in tenure groups
tg_ch  =  churn["tenure_group"].value_counts().reset_index()
tg_ch.columns  = ["tenure_group","count"]
tg_nch =  not_churn["tenure_group"].value_counts().reset_index()
tg_nch.columns = ["tenure_group","count"]

#bar - churn
trace1 = go.Bar(x = tg_ch["tenure_group"]  , y = tg_ch["count"],
                name = "Churn Customers",
                marker = dict(line = dict(width = .5,color = "black")),
                opacity = .9)

#bar - not churn
trace2 = go.Bar(x = tg_nch["tenure_group"] , y = tg_nch["count"],
                name = "Non Churn Customers",
                marker = dict(line = dict(width = .5,color = "black")),
                opacity = .9)

layout = go.Layout(dict(title = "Customer attrition in tenure groups",
                        plot_bgcolor  = "rgb(243,243,243)",
                        paper_bgcolor = "rgb(243,243,243)",
                        xaxis = dict(gridcolor = 'rgb(255, 255, 255)',
                                     title = "tenure group",
                                     zerolinewidth=1,ticklen=5,gridwidth=2),
                        yaxis = dict(gridcolor = 'rgb(255, 255, 255)',
                                     title = "count",
                                     zerolinewidth=1,ticklen=5,gridwidth=2),
                       )
                  )
data = [trace1,trace2]
fig  = go.Figure(data=data,layout=layout)
py.iplot(fig)
avg_tgc = df.groupby(["tenure_group","Churn"])[["MonthlyCharges",
                                                    "TotalCharges"]].mean().reset_index()

#function for tracing 
def mean_charges(column,aggregate) :
    tracer = go.Bar(x = avg_tgc[avg_tgc["Churn"] == aggregate]["tenure_group"],
                    y = avg_tgc[avg_tgc["Churn"] == aggregate][column],
                    name = aggregate,marker = dict(line = dict(width = 1)),
                    text = "Churn"
                   )
    return tracer

#function for layout
def layout_plot(title,xaxis_lab,yaxis_lab) :
    layout = go.Layout(dict(title = title,
                            plot_bgcolor  = "rgb(243,243,243)",
                            paper_bgcolor = "rgb(243,243,243)",
                            xaxis = dict(gridcolor = 'rgb(255, 255, 255)',title = xaxis_lab,
                                         zerolinewidth=1,ticklen=5,gridwidth=2),
                            yaxis = dict(gridcolor = 'rgb(255, 255, 255)',title = yaxis_lab,
                                         zerolinewidth=1,ticklen=5,gridwidth=2),
                           )
                      )
    return layout
    

#plot1 - mean monthly charges by tenure groups
trace1  = mean_charges("MonthlyCharges","Yes")
trace2  = mean_charges("MonthlyCharges","No")
layout1 = layout_plot("Average Monthly Charges by Tenure groups",
                      "Tenure group","Monthly Charges")
data1   = [trace1,trace2]
fig1    = go.Figure(data=data1,layout=layout1)

py.iplot(fig1)
from sklearn.preprocessing import LabelEncoder
from sklearn.preprocessing import StandardScaler

##copy data
tel_df = df.copy()
#Drop tenure group column
df = df.drop(columns = "tenure_group",axis = 1)

#customer id col
Id_col     = ['customerID']
#Target columns
target_col = ["Churn"]
#categorical columns
cat_cols   = df.nunique()[df.nunique() < 6].keys().tolist()
cat_cols   = [x for x in cat_cols if x not in target_col]
#numerical columns
num_cols   = [x for x in df.columns if x not in cat_cols + target_col + Id_col]
#Binary columns with 2 values
bin_cols   = df.nunique()[df.nunique() == 2].keys().tolist()
#Columns more than 2 values
multi_cols = [i for i in cat_cols if i not in bin_cols]

#Label encoding Binary columns
le = LabelEncoder()
for i in bin_cols :
    df[i] = le.fit_transform(df[i])
    
#Duplicating columns for multi value columns
df = pd.get_dummies(data = df,columns = multi_cols )

#Dropping customerId column
df = df.iloc[:,1:]
df.head()
df.info()
df.describe()
plt.figure(figsize=(15,8))
df.corr()['Churn'].sort_values(ascending = False).plot(kind='bar')
sns.heatmap(df.corr())
df.corr()
#separating binary columns
bi_cs = df.nunique()[df.nunique() == 2].keys()
dat_rad = df[bi_cs]

#plotting radar chart for churn and non churn customers(binary variables)
def plot_radar(df,aggregate,title) :
    data_frame = df[df["Churn"] == aggregate] 
    data_frame_x = data_frame[bi_cs].sum().reset_index()
    data_frame_x.columns  = ["feature","yes"]
    data_frame_x["no"]    = data_frame.shape[0]  - data_frame_x["yes"]
    data_frame_x  = data_frame_x[data_frame_x["feature"] != "Churn"]
    
    #count of 1's(yes)
    trace1 = go.Scatterpolar(r = data_frame_x["yes"].values.tolist(),
                             theta = data_frame_x["feature"].tolist(),
                             fill  = "toself",name = "count of 1's",
                             mode = "markers+lines",
                             marker = dict(size = 5)
                            )
    #count of 0's(No)
    trace2 = go.Scatterpolar(r = data_frame_x["no"].values.tolist(),
                             theta = data_frame_x["feature"].tolist(),
                             fill  = "toself",name = "count of 0's",
                             mode = "markers+lines",
                             marker = dict(size = 5)
                            ) 
    layout = go.Layout(dict(polar = dict(radialaxis = dict(visible = True,
                                                           side = "counterclockwise",
                                                           showline = True,
                                                           linewidth = 2,
                                                           tickwidth = 2,
                                                           gridcolor = "white",
                                                           gridwidth = 2),
                                         angularaxis = dict(tickfont = dict(size = 10),
                                                            layer = "below traces"
                                                           ),
                                         bgcolor  = "rgb(243,243,243)",
                                        ),
                            paper_bgcolor = "rgb(243,243,243)",
                            title = title,height = 700))
    
    data = [trace2,trace1]
    fig = go.Figure(data=data,layout=layout)
    py.iplot(fig)

#plot
plot_radar(dat_rad,1,"Churn -  Customers")
plot_radar(dat_rad,0,"Non Churn - Customers")
df.to_csv("PreprocessedData.csv", sep=',', encoding='utf-8')
ax = sns.scatterplot(x="tenure", y="MonthlyCharges", hue="Churn" , data=df)<jupyter_output><empty_output><jupyter_text>From this we can understand that people who are paying more per month are more likely to churn.<jupyter_code>#labels
lab = df["SeniorCitizen"].value_counts().keys().tolist()
#values
val = df["SeniorCitizen"].value_counts().values.tolist()

trace = go.Pie(labels = lab ,
               values = val ,
               marker = dict(colors =  [ 'royalblue' ,'lime'],
                             line = dict(color = "white",
                                         width =  1.3)
                            ),
               rotation = 90,
               hoverinfo = "label+value+text",
               hole = .5
              )
layout = go.Layout(dict(title = "Senior Citizens",
                        plot_bgcolor  = "rgb(243,243,243)",
                        paper_bgcolor = "rgb(243,243,243)",
                       )
                  )

data = [trace]
fig = go.Figure(data = data,layout = layout)
py.iplot(fig)
plt.figure(figsize=(12,6))
plt.subplot(121)
x = sns.countplot(x="gender", hue="Churn", data=df)


plt.subplot(122)
plt.pie(df["gender"].value_counts().values,
        labels=["Female","Male"],
        autopct="%1.0f%%",wedgeprops={"linewidth":2,"edgecolor":"white"})
my_circ = plt.Circle((0,0),.7,color = "white")
plt.gca().add_artist(my_circ)
plt.subplots_adjust(wspace = .2)
plt.title("Proportion of Gender in dataset")
plt.show()<jupyter_output><empty_output><jupyter_text>Here in gender 0 stands for Female values and 1 stands for Male values. Churn 0 stands for No Churn and 1 stands for Churn. From this plot we can infer low probability of bias based on gender.<jupyter_code>from mpl_toolkits.mplot3d import Axes3D
fig = plt.figure(figsize=(13,13))
ax  = fig.add_subplot(111,projection = "3d")

ax.scatter(df[df["Churn"] == 1][["tenure"]],df[df["Churn"] == 1][["MonthlyCharges"]]
           ,df[df["Churn"] == 1][["TotalCharges"]],
           alpha=.5,s=80,linewidth=2,edgecolor="k",color="r",label="Churn")
ax.scatter(df[df["Churn"] == 0][["tenure"]],df[df["Churn"] == 0][["MonthlyCharges"]]
           ,df[df["Churn"] == 0][["TotalCharges"]],
           alpha=.5,s=80,linewidth=2,edgecolor="k",color="lime",label="No Churn")

ax.set_xlabel("tenure",fontsize=15)
ax.set_ylabel("MonthlyCharges",fontsize=15)
ax.set_zlabel("TotalCharges",fontsize=15)
plt.legend(loc="best")
fig.set_facecolor("w")
plt.title("3D PLOT FOR Tenure VS Monthly Charges VS Total Charges",fontsize=10)
plt.show()<jupyter_output><empty_output>
{'fraction_non_alphanumeric': 0.1108433734939759, 'fraction_numerical': 0.02294394971189104, 'mean_word_length': 2.7352768538446486, 'pattern_counts': {'":': 2, '<': 46, '<?xml version=': 0, '>': 44, 'https://': 1, 'lorem ipsum': 0, 'www.': 1, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 37, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'chain_length': '9', 'dir': 'jupyter-structured-clean-dedup', 'id': '253312', 'license': 'MIT', 'n_tokens_mistral': 5919, 'n_tokens_neox': 5461, 'n_words': 1645, 'path': '.ipynb_checkpoints/Customer Retention Prediction-checkpoint.ipynb', 'repo_name': 'Dikshali/Customer-Retention-Predictive-model', 'size': '19090'}