Personal loans are a lucrative revenue stream for banks. The typical interest rate of a two year loan in the United Kingdom is around 10%. This might not sound like a lot, but in September 2022 alone UK consumers borrowed around £1.5 billion, which would mean approximately £300 million in interest generated by banks over two years!
You have been asked to work with a bank to clean and store the data they collected as part of a recent marketing campaign, which aimed to get customers to take out a personal loan. They plan to conduct more marketing campaigns going forward so would like you to set up a PostgreSQL database to store this campaign's data, designing the schema in a way that would allow data from future campaigns to be easily imported.
They have supplied you with a csv file called "bank_marketing.csv"
, which you will need to clean, reformat, and split, in order to save separate files based on the tables you will create. It is recommended to use pandas
for these tasks.
Lastly, you will write the SQL code that the bank can execute to create the tables and populate with the data from the csv files. As the bank are quite strict about their security, you'll provide the database design script as a .sql
file that they can then run.
You have been asked to design a database that will have three tables:
client
column | data type | description |
---|---|---|
id | serial | Client ID - primary key |
age | integer | Client's age in years |
job | text | Client's type of job |
marital | text | Client's marital status |
education | text | Client's level of education |
credit_default | boolean | Whether the client's credit is in default |
housing | boolean | Whether the client has an existing housing loan (mortgage) |
loan | boolean | Whether the client has an existing personal loan |
campaign
column | data type | description |
---|---|---|
campaign_id | serial | Campaign ID - primary key |
client_id | serial | Client ID - references id in the client table |
number_contacts | integer | Number of contact attempts to the client in the current campaign |
contact_duration | integer | Last contact duration in seconds |
pdays | integer | Number of days since contact in previous campaign (999 = not previously contacted) |
previous_campaign_contacts | integer | Number of contact attempts to the client in the previous campaign |
previous_outcome | boolean | Outcome of the previous campaign |
campaign_outcome | boolean | Outcome of the current campaign |
last_contact_date | date | Last date the client was contacted |
economics
column | data type | description |
---|---|---|
client_id | serial | Client ID - references id in the client table |
emp_var_rate | float | Employment variation rate (quarterly indicator) |
cons_price_idx | float | Consumer price index (monthly indicator) |
euribor_three_months | float | Euro Interbank Offered Rate (euribor) three month rate (daily indicator) |
number_employed | float | Number of employees (quarterly indicator) |
import pandas as pd
import numpy as np
#Read in CSV
bank_marketing = pd.read_csv('bank_marketing.csv')
#Split into three tables
client = bank_marketing[['client_id', 'age', 'job', 'marital', 'education', 'credit_default', 'housing', 'loan']]
campaign = bank_marketing[["client_id", "campaign", "month", "day", "duration", "pdays", "previous", "poutcome", "y"]]
economics = bank_marketing[['client_id', 'emp_var_rate', 'cons_price_idx', 'euribor3m', 'nr_employed']]
#Rename client_id in client table
client.rename(columns={"client_id": "id"}, inplace=True)
#Rename duration, y and campaign columns
campaign.rename(columns={"duration": "contact_duration", "previous": "previous_campaign_contacts", "y": "campaign_outcome", "campaign": "number_contacts", "poutcome": "previous_outcome"}, inplace=True)
#Rename euribor3m and nr_employed
economics.rename(columns={"euribor3m": "euribor_three_months", "nr_employed": "number_employed"}, inplace=True)
#Clean education column
client['education'] = client['education'].str.replace('.', '_')
client['education'] = client['education'].replace('unknown', np.NAN)
#Clean job column
client['job'] = client['job'].str.replace('.', '')
#Change campaign_outcome to binary values
campaign['campaign_outcome'] = campaign['campaign_outcome'].replace('success', 1)
campaign['campaign_outcome'] = campaign['campaign_outcome'].replace('failure', 0)
#Convert poutcome to binary values
campaign['previous_outcome'] = campaign['previous_outcome'].replace('nonexistent', np.NaN)
campaign['previous_outcome'] = campaign['previous_outcome'].replace('success', 1)
campaign['previous_outcome'] = campaign['previous_outcome'].replace('failure', 0)
#add campaign_id column
campaign['campaign_id'] = 1
#Capitalize month column
campaign['month'] = campaign['month'].str.capitalize()
#Create year column
campaign['year'] = '2022'
#Convert day to string
campaign['day'] = campaign['day'].astype(str)
#Create last_contact_date column from month, year and day
campaign['last_contact_date'] = campaign['year'] + '-' + campaign['month'] + '-' + campaign['day']
#Convert last_contact_date to datetime
campaign['last_contact_date'] = pd.to_datetime(campaign['last_contact_date'], format = '%Y-%b-%d')
#Drop no longer needed columns
campaign.drop(columns = ['month', 'day', 'year'], inplace=True)
#Save tables to csv files
campaign.to_csv('campaign.csv', index=False)
client.to_csv('client.csv', index=False)
economics.to_csv('economics.csv', index=False)
#Create client table
client_table = """CREATE TABLE client
(
id SERIAL PRIMARY KEY,
age INTEGER,
job TEXT,
marital TEXT,
education TEXT,
credit_default BOOLEAN,
housing BOOLEAN,
loan BOOLEAN
);
\copy client from 'client.csv' DELIMITER ',' CSV HEADER
"""
#Create campaign table
campaign_table = """CREATE TABLE campaign
(
campaign_id SERIAL PRIMARY KEY,
client_id SERIAL references client (id),
number_contacts INTEGER,
contact_duration INTEGER,
pdays INTEGER,
previous_campaign_contacts INTEGER,
previous_outcome BOOLEAN,
campaign_outcome BOOLEAN,
last_contact_date DATE
);
\copy campaign from 'campaign.csv' DELIMITER ',' CSV HEADER
"""
#Create economics table
economics_table = """CREATE TABLE economics
(
client_id SERIAL references client (id),
emp_var_rate FLOAT,
cons_price_idx FLOAT,
euribor_three_months FLOAT,
number_employed FLOAT
);
\copy economics from 'economics.csv' DELIMITER ',' CSV HEADER
"""