BANK CUSTOMER CHURN ANALYSIS PROJECT

 

INTRODUCTION



Customer churn refers to when customer stop doing business with a company. In banking , understanding why customers leave is very important.
This project aims to analyze customer data and identify patterns that leads to churn using Exploratory Data Analysis (EDA) techniques.
 

OBJECTIVES



* Identify factors affecting customer churn.
* Analyze customer behaviour patterns.

* Visualize relationships between features.
* Provide insights on why customers leave.
 

TOOLS & TECHNOLOGIES USED



* Python
* Pandas ( data handling)

* Matplotlib ( visualization)
* Seaborn ( advanced visualization)

* Jupyter Notebook
 

DATASET INFORMATION





* Dataset : Bank Customer Churn Dataset
* Source : Kaggle
 

ENVIRONMENT SETUP

In [1]:
pip install pandas matplotlib seaborn jupyter
Requirement already satisfied: pandas in /usr/local/lib/python3.12/dist-packages (2.2.2) Requirement already satisfied: matplotlib in /usr/local/lib/python3.12/dist-packages (3.10.0) Requirement already satisfied: seaborn in /usr/local/lib/python3.12/dist-packages (0.13.2) Collecting jupyter Downloading jupyter-1.1.1-py2.py3-none-any.whl.metadata (2.0 kB) Requirement already satisfied: numpy>=1.26.0 in /usr/local/lib/python3.12/dist-packages (from pandas) (2.0.2) Requirement already satisfied: python-dateutil>=2.8.2 in /usr/local/lib/python3.12/dist-packages (from pandas) (2.9.0.post0) Requirement already satisfied: pytz>=2020.1 in /usr/local/lib/python3.12/dist-packages (from pandas) (2025.2) Requirement already satisfied: tzdata>=2022.7 in /usr/local/lib/python3.12/dist-packages (from pandas) (2025.3) Requirement already satisfied: contourpy>=1.0.1 in /usr/local/lib/python3.12/dist-packages (from matplotlib) (1.3.3) Requirement already satisfied: cycler>=0.10 in /usr/local/lib/python3.12/dist-packages (from matplotlib) (0.12.1) Requirement already satisfied: fonttools>=4.22.0 in /usr/local/lib/python3.12/dist-packages (from matplotlib) (4.62.1) Requirement already satisfied: kiwisolver>=1.3.1 in /usr/local/lib/python3.12/dist-packages (from matplotlib) (1.5.0) Requirement already satisfied: packaging>=20.0 in /usr/local/lib/python3.12/dist-packages (from matplotlib) (26.0) Requirement already satisfied: pillow>=8 in /usr/local/lib/python3.12/dist-packages (from matplotlib) (11.3.0) Requirement already satisfied: pyparsing>=2.3.1 in /usr/local/lib/python3.12/dist-packages (from matplotlib) (3.3.2) Requirement already satisfied: notebook in /usr/local/lib/python3.12/dist-packages (from jupyter) (6.5.7) Requirement already satisfied: jupyter-console in /usr/local/lib/python3.12/dist-packages (from jupyter) (6.6.3) Requirement already satisfied: nbconvert in /usr/local/lib/python3.12/dist-packages (from jupyter) (7.17.0) Requirement already satisfied: ipykernel in /usr/local/lib/python3.12/dist-packages (from jupyter) (6.17.1) Requirement already satisfied: ipywidgets in /usr/local/lib/python3.12/dist-packages (from jupyter) (7.7.1) Collecting jupyterlab (from jupyter) Downloading jupyterlab-4.5.6-py3-none-any.whl.metadata (16 kB) Requirement already satisfied: six>=1.5 in /usr/local/lib/python3.12/dist-packages (from python-dateutil>=2.8.2->pandas) (1.17.0) Requirement already satisfied: debugpy>=1.0 in /usr/local/lib/python3.12/dist-packages (from ipykernel->jupyter) (1.8.15) Requirement already satisfied: ipython>=7.23.1 in /usr/local/lib/python3.12/dist-packages (from ipykernel->jupyter) (7.34.0) Requirement already satisfied: jupyter-client>=6.1.12 in /usr/local/lib/python3.12/dist-packages (from ipykernel->jupyter) (7.4.9) Requirement already satisfied: matplotlib-inline>=0.1 in /usr/local/lib/python3.12/dist-packages (from ipykernel->jupyter) (0.2.1) Requirement already satisfied: nest-asyncio in /usr/local/lib/python3.12/dist-packages (from ipykernel->jupyter) (1.6.0) Requirement already satisfied: psutil in /usr/local/lib/python3.12/dist-packages (from ipykernel->jupyter) (5.9.5) Requirement already satisfied: pyzmq>=17 in /usr/local/lib/python3.12/dist-packages (from ipykernel->jupyter) (26.2.1) Requirement already satisfied: tornado>=6.1 in /usr/local/lib/python3.12/dist-packages (from ipykernel->jupyter) (6.5.1) Requirement already satisfied: traitlets>=5.1.0 in /usr/local/lib/python3.12/dist-packages (from ipykernel->jupyter) (5.7.1) Requirement already satisfied: ipython-genutils~=0.2.0 in /usr/local/lib/python3.12/dist-packages (from ipywidgets->jupyter) (0.2.0) Requirement already satisfied: widgetsnbextension~=3.6.0 in /usr/local/lib/python3.12/dist-packages (from ipywidgets->jupyter) (3.6.10) Requirement already satisfied: jupyterlab-widgets>=1.0.0 in /usr/local/lib/python3.12/dist-packages (from ipywidgets->jupyter) (3.0.16) Requirement already satisfied: jupyter-core!=5.0.*,>=4.12 in /usr/local/lib/python3.12/dist-packages (from jupyter-console->jupyter) (5.9.1) Requirement already satisfied: prompt-toolkit>=3.0.30 in /usr/local/lib/python3.12/dist-packages (from jupyter-console->jupyter) (3.0.52) Requirement already satisfied: pygments in /usr/local/lib/python3.12/dist-packages (from jupyter-console->jupyter) (2.20.0) Collecting async-lru>=1.0.0 (from jupyterlab->jupyter) Downloading async_lru-2.3.0-py3-none-any.whl.metadata (7.6 kB) Requirement already satisfied: httpx<1,>=0.25.0 in /usr/local/lib/python3.12/dist-packages (from jupyterlab->jupyter) (0.28.1) Requirement already satisfied: jinja2>=3.0.3 in /usr/local/lib/python3.12/dist-packages (from jupyterlab->jupyter) (3.1.6) Collecting jupyter-lsp>=2.0.0 (from jupyterlab->jupyter) Downloading jupyter_lsp-2.3.1-py3-none-any.whl.metadata (1.8 kB) Requirement already satisfied: jupyter-server<3,>=2.4.0 in /usr/local/lib/python3.12/dist-packages (from jupyterlab->jupyter) (2.14.0) Collecting jupyterlab-server<3,>=2.28.0 (from jupyterlab->jupyter) Downloading jupyterlab_server-2.28.0-py3-none-any.whl.metadata (5.9 kB) Requirement already satisfied: notebook-shim>=0.2 in /usr/local/lib/python3.12/dist-packages (from jupyterlab->jupyter) (0.2.4) Requirement already satisfied: setuptools>=41.1.0 in /usr/local/lib/python3.12/dist-packages (from jupyterlab->jupyter) (75.2.0) Requirement already satisfied: beautifulsoup4 in /usr/local/lib/python3.12/dist-packages (from nbconvert->jupyter) (4.13.5) Requirement already satisfied: bleach!=5.0.0 in /usr/local/lib/python3.12/dist-packages (from bleach[css]!=5.0.0->nbconvert->jupyter) (6.3.0) Requirement already satisfied: defusedxml in /usr/local/lib/python3.12/dist-packages (from nbconvert->jupyter) (0.7.1) Requirement already satisfied: jupyterlab-pygments in /usr/local/lib/python3.12/dist-packages (from nbconvert->jupyter) (0.3.0) Requirement already satisfied: markupsafe>=2.0 in /usr/local/lib/python3.12/dist-packages (from nbconvert->jupyter) (3.0.3) Requirement already satisfied: mistune<4,>=2.0.3 in /usr/local/lib/python3.12/dist-packages (from nbconvert->jupyter) (3.2.0) Requirement already satisfied: nbclient>=0.5.0 in /usr/local/lib/python3.12/dist-packages (from nbconvert->jupyter) (0.10.4) Requirement already satisfied: nbformat>=5.7 in /usr/local/lib/python3.12/dist-packages (from nbconvert->jupyter) (5.10.4) Requirement already satisfied: pandocfilters>=1.4.1 in /usr/local/lib/python3.12/dist-packages (from nbconvert->jupyter) (1.5.1) Requirement already satisfied: argon2-cffi in /usr/local/lib/python3.12/dist-packages (from notebook->jupyter) (25.1.0) Requirement already satisfied: Send2Trash>=1.8.0 in /usr/local/lib/python3.12/dist-packages (from notebook->jupyter) (2.1.0) Requirement already satisfied: terminado>=0.8.3 in /usr/local/lib/python3.12/dist-packages (from notebook->jupyter) (0.18.1) Requirement already satisfied: prometheus-client in /usr/local/lib/python3.12/dist-packages (from notebook->jupyter) (0.24.1) Requirement already satisfied: nbclassic>=0.4.7 in /usr/local/lib/python3.12/dist-packages (from notebook->jupyter) (1.3.3) Requirement already satisfied: webencodings in /usr/local/lib/python3.12/dist-packages (from bleach!=5.0.0->bleach[css]!=5.0.0->nbconvert->jupyter) (0.5.1) Requirement already satisfied: tinycss2<1.5,>=1.1.0 in /usr/local/lib/python3.12/dist-packages (from bleach[css]!=5.0.0->nbconvert->jupyter) (1.4.0) Requirement already satisfied: anyio in /usr/local/lib/python3.12/dist-packages (from httpx<1,>=0.25.0->jupyterlab->jupyter) (4.13.0) Requirement already satisfied: certifi in /usr/local/lib/python3.12/dist-packages (from httpx<1,>=0.25.0->jupyterlab->jupyter) (2026.2.25) Requirement already satisfied: httpcore==1.* in /usr/local/lib/python3.12/dist-packages (from httpx<1,>=0.25.0->jupyterlab->jupyter) (1.0.9) Requirement already satisfied: idna in /usr/local/lib/python3.12/dist-packages (from httpx<1,>=0.25.0->jupyterlab->jupyter) (3.11) Requirement already satisfied: h11>=0.16 in /usr/local/lib/python3.12/dist-packages (from httpcore==1.*->httpx<1,>=0.25.0->jupyterlab->jupyter) (0.16.0) Collecting jedi>=0.16 (from ipython>=7.23.1->ipykernel->jupyter) Downloading jedi-0.19.2-py2.py3-none-any.whl.metadata (22 kB) Requirement already satisfied: decorator in /usr/local/lib/python3.12/dist-packages (from ipython>=7.23.1->ipykernel->jupyter) (4.4.2) Requirement already satisfied: pickleshare in /usr/local/lib/python3.12/dist-packages (from ipython>=7.23.1->ipykernel->jupyter) (0.7.5) Requirement already satisfied: backcall in /usr/local/lib/python3.12/dist-packages (from ipython>=7.23.1->ipykernel->jupyter) (0.2.0) Requirement already satisfied: pexpect>4.3 in /usr/local/lib/python3.12/dist-packages (from ipython>=7.23.1->ipykernel->jupyter) (4.9.0) Requirement already satisfied: entrypoints in /usr/local/lib/python3.12/dist-packages (from jupyter-client>=6.1.12->ipykernel->jupyter) (0.4) Requirement already satisfied: platformdirs>=2.5 in /usr/local/lib/python3.12/dist-packages (from jupyter-core!=5.0.*,>=4.12->jupyter-console->jupyter) (4.9.4) Requirement already satisfied: jupyter-events>=0.9.0 in /usr/local/lib/python3.12/dist-packages (from jupyter-server<3,>=2.4.0->jupyterlab->jupyter) (0.12.0) Requirement already satisfied: jupyter-server-terminals>=0.4.4 in /usr/local/lib/python3.12/dist-packages (from jupyter-server<3,>=2.4.0->jupyterlab->jupyter) (0.5.4) Requirement already satisfied: overrides>=5.0 in /usr/local/lib/python3.12/dist-packages (from jupyter-server<3,>=2.4.0->jupyterlab->jupyter) (7.7.0) Requirement already satisfied: websocket-client>=1.7 in /usr/local/lib/python3.12/dist-packages (from jupyter-server<3,>=2.4.0->jupyterlab->jupyter) (1.9.0) Requirement already satisfied: argon2-cffi-bindings in /usr/local/lib/python3.12/dist-packages (from argon2-cffi->notebook->jupyter) (25.1.0) Requirement already satisfied: babel>=2.10 in /usr/local/lib/python3.12/dist-packages (from jupyterlab-server<3,>=2.28.0->jupyterlab->jupyter) (2.18.0) Collecting json5>=0.9.0 (from jupyterlab-server<3,>=2.28.0->jupyterlab->jupyter) Downloading json5-0.14.0-py3-none-any.whl.metadata (36 kB) Requirement already satisfied: jsonschema>=4.18.0 in /usr/local/lib/python3.12/dist-packages (from jupyterlab-server<3,>=2.28.0->jupyterlab->jupyter) (4.26.0) Requirement already satisfied: requests>=2.31 in /usr/local/lib/python3.12/dist-packages (from jupyterlab-server<3,>=2.28.0->jupyterlab->jupyter) (2.32.4) Requirement already satisfied: fastjsonschema>=2.15 in /usr/local/lib/python3.12/dist-packages (from nbformat>=5.7->nbconvert->jupyter) (2.21.2) Requirement already satisfied: wcwidth in /usr/local/lib/python3.12/dist-packages (from prompt-toolkit>=3.0.30->jupyter-console->jupyter) (0.6.0) Requirement already satisfied: ptyprocess in /usr/local/lib/python3.12/dist-packages (from terminado>=0.8.3->notebook->jupyter) (0.7.0) Requirement already satisfied: soupsieve>1.2 in /usr/local/lib/python3.12/dist-packages (from beautifulsoup4->nbconvert->jupyter) (2.8.3) Requirement already satisfied: typing-extensions>=4.0.0 in /usr/local/lib/python3.12/dist-packages (from beautifulsoup4->nbconvert->jupyter) (4.15.0) Requirement already satisfied: parso<0.9.0,>=0.8.4 in /usr/local/lib/python3.12/dist-packages (from jedi>=0.16->ipython>=7.23.1->ipykernel->jupyter) (0.8.6) Requirement already satisfied: attrs>=22.2.0 in /usr/local/lib/python3.12/dist-packages (from jsonschema>=4.18.0->jupyterlab-server<3,>=2.28.0->jupyterlab->jupyter) (26.1.0) Requirement already satisfied: jsonschema-specifications>=2023.03.6 in /usr/local/lib/python3.12/dist-packages (from jsonschema>=4.18.0->jupyterlab-server<3,>=2.28.0->jupyterlab->jupyter) (2025.9.1) Requirement already satisfied: referencing>=0.28.4 in /usr/local/lib/python3.12/dist-packages (from jsonschema>=4.18.0->jupyterlab-server<3,>=2.28.0->jupyterlab->jupyter) (0.37.0) Requirement already satisfied: rpds-py>=0.25.0 in /usr/local/lib/python3.12/dist-packages (from jsonschema>=4.18.0->jupyterlab-server<3,>=2.28.0->jupyterlab->jupyter) (0.30.0) Requirement already satisfied: python-json-logger>=2.0.4 in /usr/local/lib/python3.12/dist-packages (from jupyter-events>=0.9.0->jupyter-server<3,>=2.4.0->jupyterlab->jupyter) (4.1.0) Requirement already satisfied: pyyaml>=5.3 in /usr/local/lib/python3.12/dist-packages (from jupyter-events>=0.9.0->jupyter-server<3,>=2.4.0->jupyterlab->jupyter) (6.0.3) Requirement already satisfied: rfc3339-validator in /usr/local/lib/python3.12/dist-packages (from jupyter-events>=0.9.0->jupyter-server<3,>=2.4.0->jupyterlab->jupyter) (0.1.4) Requirement already satisfied: rfc3986-validator>=0.1.1 in /usr/local/lib/python3.12/dist-packages (from jupyter-events>=0.9.0->jupyter-server<3,>=2.4.0->jupyterlab->jupyter) (0.1.1) Requirement already satisfied: charset_normalizer<4,>=2 in /usr/local/lib/python3.12/dist-packages (from requests>=2.31->jupyterlab-server<3,>=2.28.0->jupyterlab->jupyter) (3.4.6) Requirement already satisfied: urllib3<3,>=1.21.1 in /usr/local/lib/python3.12/dist-packages (from requests>=2.31->jupyterlab-server<3,>=2.28.0->jupyterlab->jupyter) (2.5.0) Requirement already satisfied: cffi>=1.0.1 in /usr/local/lib/python3.12/dist-packages (from argon2-cffi-bindings->argon2-cffi->notebook->jupyter) (2.0.0) Requirement already satisfied: pycparser in /usr/local/lib/python3.12/dist-packages (from cffi>=1.0.1->argon2-cffi-bindings->argon2-cffi->notebook->jupyter) (3.0) Requirement already satisfied: fqdn in /usr/local/lib/python3.12/dist-packages (from jsonschema[format-nongpl]>=4.18.0->jupyter-events>=0.9.0->jupyter-server<3,>=2.4.0->jupyterlab->jupyter) (1.5.1) Requirement already satisfied: isoduration in /usr/local/lib/python3.12/dist-packages (from jsonschema[format-nongpl]>=4.18.0->jupyter-events>=0.9.0->jupyter-server<3,>=2.4.0->jupyterlab->jupyter) (20.11.0) Requirement already satisfied: jsonpointer>1.13 in /usr/local/lib/python3.12/dist-packages (from jsonschema[format-nongpl]>=4.18.0->jupyter-events>=0.9.0->jupyter-server<3,>=2.4.0->jupyterlab->jupyter) (3.1.1) Requirement already satisfied: rfc3987-syntax>=1.1.0 in /usr/local/lib/python3.12/dist-packages (from jsonschema[format-nongpl]>=4.18.0->jupyter-events>=0.9.0->jupyter-server<3,>=2.4.0->jupyterlab->jupyter) (1.1.0) Requirement already satisfied: uri-template in /usr/local/lib/python3.12/dist-packages (from jsonschema[format-nongpl]>=4.18.0->jupyter-events>=0.9.0->jupyter-server<3,>=2.4.0->jupyterlab->jupyter) (1.3.0) Requirement already satisfied: webcolors>=24.6.0 in /usr/local/lib/python3.12/dist-packages (from jsonschema[format-nongpl]>=4.18.0->jupyter-events>=0.9.0->jupyter-server<3,>=2.4.0->jupyterlab->jupyter) (25.10.0) Requirement already satisfied: lark>=1.2.2 in /usr/local/lib/python3.12/dist-packages (from rfc3987-syntax>=1.1.0->jsonschema[format-nongpl]>=4.18.0->jupyter-events>=0.9.0->jupyter-server<3,>=2.4.0->jupyterlab->jupyter) (1.3.1) Requirement already satisfied: arrow>=0.15.0 in /usr/local/lib/python3.12/dist-packages (from isoduration->jsonschema[format-nongpl]>=4.18.0->jupyter-events>=0.9.0->jupyter-server<3,>=2.4.0->jupyterlab->jupyter) (1.4.0) Downloading jupyter-1.1.1-py2.py3-none-any.whl (2.7 kB) Downloading jupyterlab-4.5.6-py3-none-any.whl (12.4 MB)  ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━ 12.4/12.4 MB 70.4 MB/s eta 0:00:00 [?25hDownloading async_lru-2.3.0-py3-none-any.whl (8.4 kB) Downloading jupyter_lsp-2.3.1-py3-none-any.whl (77 kB)  ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━ 77.5/77.5 kB 7.6 MB/s eta 0:00:00 [?25hDownloading jupyterlab_server-2.28.0-py3-none-any.whl (59 kB)  ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━ 59.8/59.8 kB 4.6 MB/s eta 0:00:00 [?25hDownloading jedi-0.19.2-py2.py3-none-any.whl (1.6 MB)  ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━ 1.6/1.6 MB 76.3 MB/s eta 0:00:00 [?25hDownloading json5-0.14.0-py3-none-any.whl (36 kB) Installing collected packages: json5, jedi, async-lru, jupyterlab-server, jupyter-lsp, jupyterlab, jupyter Successfully installed async-lru-2.3.0 jedi-0.19.2 json5-0.14.0 jupyter-1.1.1 jupyter-lsp-2.3.1 jupyterlab-4.5.6 jupyterlab-server-2.28.0
 

IMPORT & UPLOAD FILE

In [2]:
from google.colab import files
uploaded = files.upload()
Upload widget is only available when the cell has been executed in the current browser session. Please rerun this cell to enable.
Saving churn.csv to churn.csv
 

LOAD DATASET

In [3]:
import pandas as pd
df = pd.read_csv('churn.csv')
df.head()
Out[3]:
RowNumber CustomerId Surname CreditScore Geography Gender Age Tenure Balance NumOfProducts HasCrCard IsActiveMember EstimatedSalary Exited
0 1 15634602 Hargrave 619 France Female 42 2 0.00 1 1 1 101348.88 1
1 2 15647311 Hill 608 Spain Female 41 1 83807.86 1 0 1 112542.58 0
2 3 15619304 Onio 502 France Female 42 8 159660.80 3 1 0 113931.57 1
3 4 15701354 Boni 699 France Female 39 1 0.00 2 0 0 93826.63 0
4 5 15737888 Mitchell 850 Spain Female 43 2 125510.82 1 1 1 79084.10 0
 

DATA UNDERSTANDING

In [4]:
df.info()
df.describe()
df.columns
<class 'pandas.core.frame.DataFrame'> RangeIndex: 10000 entries, 0 to 9999 Data columns (total 14 columns): # Column Non-Null Count Dtype --- ------ -------------- ----- 0 RowNumber 10000 non-null int64 1 CustomerId 10000 non-null int64 2 Surname 10000 non-null object 3 CreditScore 10000 non-null int64 4 Geography 10000 non-null object 5 Gender 10000 non-null object 6 Age 10000 non-null int64 7 Tenure 10000 non-null int64 8 Balance 10000 non-null float64 9 NumOfProducts 10000 non-null int64 10 HasCrCard 10000 non-null int64 11 IsActiveMember 10000 non-null int64 12 EstimatedSalary 10000 non-null float64 13 Exited 10000 non-null int64 dtypes: float64(2), int64(9), object(3) memory usage: 1.1+ MB
Out[4]:
Index(['RowNumber', 'CustomerId', 'Surname', 'CreditScore', 'Geography',
       'Gender', 'Age', 'Tenure', 'Balance', 'NumOfProducts', 'HasCrCard',
       'IsActiveMember', 'EstimatedSalary', 'Exited'],
      dtype='object')
 

DATA CLEANING & PRE-PROCESSING

 

Remove Duplicates

In [6]:
df.drop_duplicates(inplace=True)
 

Handle Missing Values

In [8]:
df.isnull().sum()
Out[8]:
0
RowNumber 0
CustomerId 0
Surname 0
CreditScore 0
Geography 0
Gender 0
Age 0
Tenure 0
Balance 0
NumOfProducts 0
HasCrCard 0
IsActiveMember 0
EstimatedSalary 0
Exited 0

 

Convert Categorical Data

In [10]:
df["Gender"]=df['Gender'].map({'Male':1,'Female':0})
df.head()
Out[10]:
RowNumber CustomerId Surname CreditScore Geography Gender Age Tenure Balance NumOfProducts HasCrCard IsActiveMember EstimatedSalary Exited
0 1 15634602 Hargrave 619 France NaN 42 2 0.00 1 1 1 101348.88 1
1 2 15647311 Hill 608 Spain NaN 41 1 83807.86 1 0 1 112542.58 0
2 3 15619304 Onio 502 France NaN 42 8 159660.80 3 1 0 113931.57 1
3 4 15701354 Boni 699 France NaN 39 1 0.00 2 0 0 93826.63 0
4 5 15737888 Mitchell 850 Spain NaN 43 2 125510.82 1 1 1 79084.10 0
 

EXPLORATORY DATA ANALYSIS (EDA)

 

Age Distribution

In [11]:
import seaborn as sns
import matplotlib.pyplot as plt
sns.histplot(df['Age'],bins=20,kde=True)
plt.title('Age Distribution')
plt.show()
Output
 

Credit Score Distribution

In [12]:
sns.histplot(df['CreditScore'],bins=20,kde=True)
plt.title('Credit Score Distribution')
plt.show()
Output
 

Balance Distribution

In [13]:
sns.histplot(df['Balance'],bins=20,kde=True)
plt.title('Balance Distribution')
plt.show()
Output
 

Tenure Distribution

In [14]:
sns.histplot(df['Tenure'],bins=20,kde=True)
plt.title('Tenure Distribution')
plt.show()
Output
 

CHURN ANALYSIS

 

Churn Count

In [15]:
sns.countplot(x='Exited',data=df)
plt.title('Churn Count')
plt.show()
Output
 

Churn vs Age

In [16]:
sns.boxplot(x='Exited',y='Age',data=df)
plt.title('Churn vs Age')
plt.show()
Output
 

Churn vs Balance

In [17]:
sns.boxplot(x='Exited',y='Balance',data=df)
plt.title('Churn vs Balance')
plt.show()
Output
 

Churn vs Credit Score

In [18]:
sns.boxplot(x='Exited',y='CreditScore',data=df)
plt.title('Churn vs Credit Score')
plt.show()
Output
 

CORRELATION HEATMAP

In [20]:
plt.figure(figsize=(10,8))
# Select only numeric columns for correlation calculation
numeric_df = df.select_dtypes(include=['number'])
corr = numeric_df.corr()
sns.heatmap(corr,annot=True)
plt.title("Correlation Heatmap")
plt.show()
Output
 

KEY INSIGHTS





* Customers with low credit scores are more likely to churn.
* Customers with high balance tend to leave more.

* Older customers show higher churn rate.
* Customers with short tenure are more likely to exit.
 

CONCLUSION


This project analyzed bank customer data to understand churn behaviour.

Key Findings:


* Credit score , balance and age significantly influence churn.
* Customers with low engagement or short tenure are at higher risk.

* Banks should focus on customer retention startegies like:


* Better customer service.
* Personalized offers.

* Loyality programs.