Challenge

Project 2 - EDA on Vehicle Insurance Customer Data

import pandas as pd
import numpy as np
import matplotlib.pyplot as plt

# Loading the data files

df1 = pd.read_csv("customer_details.csv")

df2 = pd.read_csv("customer_policy_details.csv")
1. Add the column names to both datasets:
1.(i) Adding columns to customer details table

headers = ['customer_id','Gender','age','driving licence present','region code','previously insured','vehicle age','vehicle damage']

df1.columns=headers

df1.head()
customer_id Gender age driving licence present region code previously insured vehicle age vehicle damage
0 1.0 Male 44.0 1.0 28.0 0.0 > 2 Years Yes
1 2.0 Male 76.0 1.0 3.0 0.0 1-2 Year No
2 3.0 Male 47.0 1.0 28.0 0.0 > 2 Years Yes
3 4.0 Male 21.0 1.0 11.0 1.0 < 1 Year No
4 5.0 Female 29.0 1.0 41.0 1.0 < 1 Year No


1.(ii) Adding columns to customer policy details table
df2.columns=['customer_id','annual premium (in Rs)','sales channel code','vintage','responce']

df2.head()
customer_id annual premium (in Rs) sales channel code vintage responce
0 1.0 40454.0 26.0 217.0 1.0
1 2.0 33536.0 26.0 183.0 0.0
2 3.0 38294.0 26.0 27.0 1.0
3 4.0 28619.0 152.0 203.0 0.0
4 5.0 27496.0 152.0 39.0 0.0

2. Checking and cleaning Data quality
2.(i). NULL Values

2.i.(a). Generate a summary of count of all the null values column wise

# the column wise count of null values on customer details table

df1_null = df1.isnull()
for i in df1_null.columns.values.tolist():
print(i)
print(df1_null[i].value_counts())
print("")​
customer_id
False 380723
True 386
Name: customer_id, dtype: int64

Gender
False 380741
True 368
Name: Gender, dtype: int64

age
False 380741
True 368
Name: age, dtype: int64

driving licence present
False 380716
True 393
Name: driving licence present, dtype: int64

region code
False 380717
True 392
Name: region code, dtype: int64

previously insured
False 380728
True 381
Name: previously insured, dtype: int64

vehicle age
False 380728
True 381
Name: vehicle age, dtype: int64

vehicle damage
False 380702
True 407
Name: vehicle damage, dtype: int64

SUMMARY OF NULL VALUES ON CUSTOMER DETAILS TABLE

customer_id has 386 null values

Gender has 368 null values

age has 368 null values

driving licence present has 393 null values

region code has 392 null values

previously insured has 381 null values

vehicle age has 381 null values

vehicle damage has 407 null values

# the column wise count of null values on customer policy details table

df2_null = df2.isnull()

for i in df2_null.columns.values.tolist():
print(i)
print(df2_null[i].value_counts())
print("")
customer_id
False 380722
True 387
Name: customer_id, dtype: int64

annual premium (in Rs)
False 380763
True 346
Name: annual premium (in Rs), dtype: int64

sales channel code
False 380709
True 400
Name: sales channel code, dtype: int64

vintage
False 380721
True 388
Name: vintage, dtype: int64

responce
False 380748
True 361
Name: responce, dtype: int64

SUMMARY OF NULL VALUES ON CUSTOMER-POLICY-DETAILS TABLE

customer_id has 387 null values

annual premium has 346 null values

sales channel code has 400 null values

vintage has 388 null values

responce has 361 null values


2.i.(b). Droppinf NULL values for customer_id

# Dropping the rows that contains null values of customr_id on customer details table
df1.dropna(subset=['customer_id'], axis=0,inplace=True)

# resetting index because some rows deleted
df1.reset_index(drop = True, inplace = True)

# Dropping the rows that contains null values of customr_id on customer policy details table

df2.dropna(subset=['customer_id'], axis=0,inplace=True)

# resetting index because some rows deleted
df2.reset_index(drop = True, inplace = True)

2.i.(c). Replacing all null values for numeric columns by mean

df1.head()
customer_id Gender age driving licence present region code previously insured vehicle age vehicle damage
0 1.0 Male 44.0 1.0 28.0 0.0 > 2 Years Yes
1 2.0 Male 76.0 1.0 3.0 0.0 1-2 Year No
2 3.0 Male 47.0 1.0 28.0 0.0 > 2 Years Yes
3 4.0 Male 21.0 1.0 11.0 1.0 < 1 Year No
4 5.0 Female 29.0 1.0 41.0 1.0 < 1 Year No
In this table

age,and region code contains numerical data
where as driving licence present and previously insured contains categorical data.

# Replacing the NaN values of age by its mean value

df1['age'].fillna(df1['age'].mean(),inplace = True)


# Replacing the NaN values of region code by its mean value

df1['region code'].fillna(df1['region code'].mean(),inplace = True)

df2.head()
customer_id annual premium (in Rs) sales channel code vintage responce
0 1.0 40454.0 26.0 217.0 1.0
1 2.0 33536.0 26.0 183.0 0.0
2 3.0 38294.0 26.0 27.0 1.0
3 4.0 28619.0 152.0 203.0 0.0
4 5.0 27496.0 152.0 39.0 0.0
In this table

annual premium, sales channel code, and vintage contains numerical data
where as responce has categorical data
# Replacing the NaN values of annual premium by its mean value
df2['annual premium (in Rs)'].fillna(df2['annual premium (in Rs)'].mean(),inplace = True)

# Replacing the NaN values of sales channel code by its mean value
df2['sales channel code'].fillna(df2['sales channel code'].mean(),inplace = True)

# Replacing the NaN values of vintage by its mean value
df2['vintage'].fillna(df2['vintage'].mean(),inplace = True)

2.i.(d) Repalcing categorical null values by its mode.
# it replaces the null values with the value which exist maximum no of times i.e. mode
df1['driving licence present'].fillna (df1['driving licence present'].mode()[0], inplace=True)

# it replaces the null values with the value which exist maximum no of times i.e. mode
df1['previously insured'].fillna (df1['previously insured'].mode()[0], inplace=True)

# it replaces the null values with the value which exist maximum no of times i.e. mode

df2['responce'].fillna(df2['responce'].mode()[0], inplace=True)

2.(ii) OUTLIERS
2.ii.(a). Summary of Count of Outliers
In customer details table we need to calculate outliers for columns age and regional code.others are non-numerical columns so ignore them

# this is the function to boxplot for easy visualisation of outliers..

def plot_boxplot(df,ft):
df.boxplot(column=[ft])
plt.grid(False)
plt.show()

plot_boxplot(df1,'age')

plot_boxplot(df1,'region code')

from the above boxplot figures we can easily understand there are no outliers for customer details table.
lets see summary of the outliers for the customer details..

# this functions finds outliers if present by IQR method..

def finding_outliers(df):
q1 = df.quantile(0.25)
q3 = df.quantile(0.75)
iqr = q3-q1
outlier = df[((df<(q1-1.5*iqr)) | (df>(q3+1.5*iqr)))]
return outlier

outliers = finding_outliers(df1['age'])

print('Number of outliers :',len(outliers))
print('Maximum outlier value :',outliers.max())
print('Minimum outlier value :',outliers.min())
Number of outliers : 0
Maximum outlier value : nan
Minimum outlier value : nan

outliers = finding_outliers(df1['region code'])

print('Number of outliers :',len(outliers))
print('Maximum outlier value :',outliers.max())
print('Minimum outlier value :',outliers.min())
Number of outliers : 0
Maximum outlier value : nan
Minimum outlier value : nan

from the above results we can conclude that customer details table doesn't have outliers..

Finding outliers for customer policy details..
plot_boxplot(df2,'annual premium (in Rs)')

plot_boxplot(df2,'sales channel code')

plot_boxplot(df2,'vintage')

From the above boxplot graphs we can conclude that only column annual premium has outliers.. lets find the summary of the outliers..

outliers = finding_outliers(df2['annual premium (in Rs)'])

print('Number of outliers :',len(outliers))
print('Maximum outlier value :',outliers.max())
print('Minimum outlier value :',outliers.min())
Number of outliers : 10332
Maximum outlier value : 540165.0
Minimum outlier value : 61858.0

outliers = finding_outliers(df2['sales channel code'])

print('Number of outliers :',len(outliers))
print('Maximum outlier value :',outliers.max())
print('Minimum outlier value :',outliers.min())
Number of outliers : 0
Maximum outlier value : nan
Minimum outlier value : nan

outliers = finding_outliers(df2['vintage'])

print('Number of outliers :',len(outliers))
print('Maximum outlier value :',outliers.max())
print('Minimum outlier value :',outliers.min())
Number of outliers : 0
Maximum outlier value : nan
Minimum outlier value : nan

2.ii.(b).Replacing the outliers with mean values
def replace_outlier(df):
q1 = df.quantile(0.25)
q3 = df.quantile(0.75)
iqr = q3-q1
upper = df[~(df>(q3+1.5*iqr))].max()
lower = df[~(df<(q1-1.5*iqr))].min()
df = np.where(df>upper,df.mean(),np.where(df<lower,df.mean(),df))
return df

df2['annual premium (in Rs)'] = replace_outlier(df2['annual premium (in Rs)'])

2.(iii). Remove white spaces
df1.apply(lambda x: x.str.strip() if x.dtype=='object' else x)
customer_id Gender age driving licence present region code previously insured vehicle age vehicle damage
0 1.0 Male 44.0 1.0 28.0 0.0 > 2 Years Yes
1 2.0 Male 76.0 1.0 3.0 0.0 1-2 Year No
2 3.0 Male 47.0 1.0 28.0 0.0 > 2 Years Yes
3 4.0 Male 21.0 1.0 11.0 1.0 < 1 Year No
4 5.0 Female 29.0 1.0 41.0 1.0 < 1 Year No
... ... ... ... ... ... ... ... ...
380718 381105.0 Male 74.0 1.0 26.0 1.0 1-2 Year No
380719 381106.0 Male 30.0 1.0 37.0 1.0 < 1 Year No
380720 381107.0 Male 21.0 1.0 30.0 1.0 < 1 Year No
380721 381108.0 Female 68.0 1.0 14.0 0.0 > 2 Years Yes
380722 381109.0 Male 46.0 1.0 29.0 0.0 1-2 Year No

2.(iv). Case Correction
convert all the characters to upper case.

df1.apply(lambda x: x.str.upper() if x.dtype=='object' else x)
customer_id Gender age driving licence present region code previously insured vehicle age vehicle damage
0 1.0 MALE 44.0 1.0 28.0 0.0 > 2 YEARS YES
1 2.0 MALE 76.0 1.0 3.0 0.0 1-2 YEAR NO
2 3.0 MALE 47.0 1.0 28.0 0.0 > 2 YEARS YES
3 4.0 MALE 21.0 1.0 11.0 1.0 < 1 YEAR NO
4 5.0 FEMALE 29.0 1.0 41.0 1.0 < 1 YEAR NO
... ... ... ... ... ... ... ... ...
380718 381105.0 MALE 74.0 1.0 26.0 1.0 1-2 YEAR NO
380719 381106.0 MALE 30.0 1.0 37.0 1.0 < 1 YEAR NO
380720 381107.0 MALE 21.0 1.0 30.0 1.0 < 1 YEAR NO
380721 381108.0 FEMALE 68.0 1.0 14.0 0.0 > 2 YEARS YES
380722 381109.0 MALE 46.0 1.0 29.0 0.0 1-2 YEAR NO

2.(v). Convert nominal data into dummy variables

Indicator Variable (or Dummy Variable)
What is an indicator variable?
An indicator variable (or dummy variable) is a numerical variable used to label categories. They are called 'dummies' because the numbers themselves don't have inherent meaning.
Why we use indicator variables?
We use indicator variables so we can use categorical variables for regression

# Creating dummy variable for vehicle damage

dummy_variable_1 = pd.get_dummies(df1["vehicle damage"])

dummy_variable_1.head()
No Yes
0 0 1
1 1 0
2 0 1
3 1 0
4 1 0

# Changing the column names for dummy variable

dummy_variable_1.rename(columns={'No':'vehicle-damage-No', 'Yes':'vehicle-damage-Yes'}, inplace=True)

dummy_variable_1.head()
vehicle-damage-No vehicle-damage-Yes
0 0 1
1 1 0
2 0 1
3 1 0
4 1 0

# merge data frame "df1" and "dummy_variable_1"
df1 = pd.concat([df1, dummy_variable_1], axis=1)

# drop original column "vehicle damage" from "df1"
df1.drop("vehicle damage", axis = 1, inplace=True)

2.(vi). Drop Duplicates
# Dropping duplicates from customer details table

df1.drop_duplicates(inplace=True)


# Dropping duplicates from customer policy details table

df2.drop_duplicates(inplace=True)

3. Merging the data sets.
master_data = pd.merge(df1,df2,on='customer_id')

master_data
customer_id Gender age driving licence present region code previously insured vehicle age vehicle-damage-No vehicle-damage-Yes annual premium (in Rs) sales channel code vintage responce
0 1.0 Male 44.0 1.0 28.0 0.0 > 2 Years 0 1 40454.0 26.0 217.0 1.0
1 2.0 Male 76.0 1.0 3.0 0.0 1-2 Year 1 0 33536.0 26.0 183.0 0.0
2 3.0 Male 47.0 1.0 28.0 0.0 > 2 Years 0 1 38294.0 26.0 27.0 1.0
3 4.0 Male 21.0 1.0 11.0 1.0 < 1 Year 1 0 28619.0 152.0 203.0 0.0
4 5.0 Female 29.0 1.0 41.0 1.0 < 1 Year 1 0 27496.0 152.0 39.0 0.0
... ... ... ... ... ... ... ... ... ... ... ... ... ...
380331 381105.0 Male 74.0 1.0 26.0 1.0 1-2 Year 1 0 30170.0 26.0 88.0 0.0
380332 381106.0 Male 30.0 1.0 37.0 1.0 < 1 Year 1 0 40016.0 152.0 131.0 0.0
380333 381107.0 Male 21.0 1.0 30.0 1.0 < 1 Year 1 0 35118.0 160.0 161.0 0.0
380334 381108.0 Female 68.0 1.0 14.0 0.0 > 2 Years 0 1 44617.0 124.0 74.0 0.0
380335 381109.0 Male 46.0 1.0 29.0 0.0 1-2 Year 1 0 41777.0 26.0 237.0 0.0

4. getting required data for decisions
4.(i). Gender wise average annual premium
gender_data = master_data.groupby('Gender')['annual premium (in Rs)'].mean()

gender_data
Gender
Female 29273.474247
Male 29323.022594
Name: annual premium (in Rs), dtype: float64

# plots a linear graph

gender_data.plot()

# plotting a bar graph

gender_data.plot.bar(title='Gender vs average annual premium')

4.(ii). age wise average annual premium
age_data = master_data.groupby('age')['annual premium (in Rs)'].mean()

age_data
age
20.0 26342.073517
21.0 29751.791916
22.0 29946.848634
23.0 29838.344763
24.0 30125.557096
...
81.0 29287.910702
82.0 36480.586199
83.0 28995.818172
84.0 35440.818182
85.0 26637.454525
Name: annual premium (in Rs), Length: 67, dtype: float64
# showing the results on a linear graph

age_data.plot(xlabel="age",ylabel="annual premium(in Rs)",title="Age vs Average annual premium")

# plotting a bar graph

age_data.plot.bar()

4.(iii). Checking Balanced between gender or not..

master_data.groupby('Gender').count()
customer_id age driving licence present region code previously insured vehicle age vehicle-damage-No vehicle-damage-Yes annual premium (in Rs) sales channel code vintage responce
Gender
Female 174485 174485 174485 174485 174485 174309 174485 174485 174485 174485 174485 174485
Male 205484 205484 205484 205484 205484 205279 205484 205484 205484 205484 205484 205484

summary
The ratio between male and female is approximately 1. (1.177)
4.(iv). Vehicle age wise average annual premium

vehicle_age = master_data.groupby('vehicle age')['annual premium (in Rs)'].mean()

vehicle_age
vehicle age
1-2 Year 29099.066738
< 1 Year 29188.150594
> 2 Years 32943.540830
Name: annual premium (in Rs), dtype: float64

vehicle_age.plot() # linear graph

vehicle_age.plot.bar() # bar graph

5. Correlation between age and annual premuim
Pearson Correlation
The Pearson Correlation measures the linear dependence between two variables X and Y.

The resulting coefficient is a value between -1 and 1 inclusive, where:

1: Perfect positive linear correlation.
0: No linear correlation, the two variables most likely do not affect each other.
-1: Perfect negative linear correlation.
Correlation coefficient < -0.5 - Strong negative relationship

Correlation coefficient > 0.5 - Strong positive relationship

-0.5 < Correlation coefficient < 0.5 - There is no relationship.

# finding the correlation coefficient in pandas

master_data['age'].corr(master_data['annual premium (in Rs)'])
0.0506575892861754

# Matrix form of correlation

master_data[['age','annual premium (in Rs)']].corr()​
age annual premium (in Rs)
age 1.000000 0.050658
annual premium (in Rs) 0.050658 1.000000

Summary
Since the Person coefficient lies between 0.5 and -.5, So no relation between age and annual premium

Your portfolio, next

Ship work like this
in your own course.

Talk to a career counsellor

Free 20-minute call. We'll map the right course to where you want to work.

By submitting you agree to our Terms and Privacy Policy.