Click on Prediction from an Advertising Company Website

In this project we will be working with a fake advertising data set, indicating whether or not a particular internet user clicked on an Advertisement on a company website. We will try to create a model that will predict whether or not they will click on an ad based off the features of that user.

This data set contains the following features:

  • 'Daily Time Spent on Site': consumer time on site in minutes
  • 'Age': cutomer age in years
  • 'Area Income': Avg. Income of geographical area of consumer
  • 'Daily Internet Usage': Avg. minutes a day consumer is on the internet
  • 'Ad Topic Line': Headline of the advertisement
  • 'City': City of consumer
  • 'Male': Whether or not consumer was male
  • 'Country': Country of consumer
  • 'Timestamp': Time at which consumer clicked on Ad or closed window
  • 'Clicked on Ad': 0 or 1 indicated clicking on Ad

Get started

In [1]:
import pandas as pd
import numpy as np
import matplotlib.pyplot as plt
import seaborn as sns
%matplotlib inline

Get the Data

Load Dataset provided into our dataframe.

In [2]:
ads = pd.read_csv('advertising.csv')
In [3]:
ads.head()
Out[3]:
Daily Time Spent on Site Age Area Income Daily Internet Usage Ad Topic Line City Male Country Timestamp Clicked on Ad
0 68.95 35 61833.90 256.09 Cloned 5thgeneration orchestration Wrightburgh 0 Tunisia 2016-03-27 00:53:11 0
1 80.23 31 68441.85 193.77 Monitored national standardization West Jodi 1 Nauru 2016-04-04 01:39:02 0
2 69.47 26 59785.94 236.50 Organic bottom-line service-desk Davidton 0 San Marino 2016-03-13 20:35:42 0
3 74.15 29 54806.18 245.89 Triple-buffered reciprocal time-frame West Terrifurt 1 Italy 2016-01-10 02:31:19 0
4 68.37 35 73889.99 225.58 Robust logistical utilization South Manuel 0 Iceland 2016-06-03 03:36:18 0

Use info and describe() on ad_data

In [5]:
ads.info()
<class 'pandas.core.frame.DataFrame'>
RangeIndex: 1000 entries, 0 to 999
Data columns (total 10 columns):
Daily Time Spent on Site    1000 non-null float64
Age                         1000 non-null int64
Area Income                 1000 non-null float64
Daily Internet Usage        1000 non-null float64
Ad Topic Line               1000 non-null object
City                        1000 non-null object
Male                        1000 non-null int64
Country                     1000 non-null object
Timestamp                   1000 non-null object
Clicked on Ad               1000 non-null int64
dtypes: float64(3), int64(3), object(4)
memory usage: 78.2+ KB
In [6]:
ads.describe()
Out[6]:
Daily Time Spent on Site Age Area Income Daily Internet Usage Male Clicked on Ad
count 1000.000000 1000.000000 1000.000000 1000.000000 1000.000000 1000.00000
mean 65.000200 36.009000 55000.000080 180.000100 0.481000 0.50000
std 15.853615 8.785562 13414.634022 43.902339 0.499889 0.50025
min 32.600000 19.000000 13996.500000 104.780000 0.000000 0.00000
25% 51.360000 29.000000 47031.802500 138.830000 0.000000 0.00000
50% 68.215000 35.000000 57012.300000 183.130000 0.000000 0.50000
75% 78.547500 42.000000 65470.635000 218.792500 1.000000 1.00000
max 91.430000 61.000000 79484.800000 269.960000 1.000000 1.00000
In [7]:
print(ads[ads['Clicked on Ad'] == 1]['Age'].mean())
print(len(ads[ads['Clicked on Ad'] == 1]))
40.334
500

500 website visitors Clicked on Ad which happens to be half of the total record number, meaning 500 also did not click on ad

In [8]:
ads.columns
Out[8]:
Index(['Daily Time Spent on Site', 'Age', 'Area Income',
       'Daily Internet Usage', 'Ad Topic Line', 'City', 'Male', 'Country',
       'Timestamp', 'Clicked on Ad'],
      dtype='object')
In [9]:
ad_data = ads.loc[(ads['Clicked on Ad'] == 1) | (ads['Clicked on Ad'] == 0),
                  ['Daily Time Spent on Site','Area Income','Age','Daily Internet Usage', 'City', 'Male','Timestamp','Clicked on Ad']]
ad_data.head()
Out[9]:
Daily Time Spent on Site Area Income Age Daily Internet Usage City Male Timestamp Clicked on Ad
0 68.95 61833.90 35 256.09 Wrightburgh 0 2016-03-27 00:53:11 0
1 80.23 68441.85 31 193.77 West Jodi 1 2016-04-04 01:39:02 0
2 69.47 59785.94 26 236.50 Davidton 0 2016-03-13 20:35:42 0
3 74.15 54806.18 29 245.89 West Terrifurt 1 2016-01-10 02:31:19 0
4 68.37 73889.99 35 225.58 South Manuel 0 2016-06-03 03:36:18 0
In [10]:
clicked = ads.loc[(ads['Clicked on Ad'] == 1),['Daily Time Spent on Site','Area Income','Age','Daily Internet Usage', 'City', 'Male','Timestamp', 'Clicked on Ad']]

notclicked = ads.loc[(ads['Clicked on Ad'] == 0),['Daily Time Spent on Site','Area Income','Age','Daily Internet Usage', 'City', 'Male','Timestamp', 'Clicked on Ad']]

clicked.head()
Out[10]:
Daily Time Spent on Site Area Income Age Daily Internet Usage City Male Timestamp Clicked on Ad
7 66.00 24593.33 48 131.76 Port Jefferybury 1 2016-03-07 01:40:15 1
10 47.64 45632.51 49 122.02 West Brandonton 0 2016-03-16 20:19:01 1
12 69.57 51636.92 48 113.12 West Katiefurt 1 2016-06-03 01:14:41 1
14 42.95 30976.00 33 143.56 West William 0 2016-03-24 09:31:49 1
15 63.45 52182.23 23 140.64 New Travistown 1 2016-03-09 03:41:30 1
In [11]:
notclicked.head()
Out[11]:
Daily Time Spent on Site Area Income Age Daily Internet Usage City Male Timestamp Clicked on Ad
0 68.95 61833.90 35 256.09 Wrightburgh 0 2016-03-27 00:53:11 0
1 80.23 68441.85 31 193.77 West Jodi 1 2016-04-04 01:39:02 0
2 69.47 59785.94 26 236.50 Davidton 0 2016-03-13 20:35:42 0
3 74.15 54806.18 29 245.89 West Terrifurt 1 2016-01-10 02:31:19 0
4 68.37 73889.99 35 225.58 South Manuel 0 2016-06-03 03:36:18 0

Exploratory Data Analysis

Let's use seaborn to explore the data!

Try recreating the plots shown below!

Create a histogram of the Age

In [12]:
sns.set_style('whitegrid')
ad_data['Age'].hist(bins=30)
plt.xlabel('Age')
Out[12]:
<matplotlib.text.Text at 0x1c0e927f470>
In [13]:
cor = ad_data['Daily Internet Usage'].corr(ad_data['Area Income'])
cor
Out[13]:
0.33749553286527628

Create a jointplot showing Area Income versus Age.

In [14]:
sns.jointplot(x='Age',y='Area Income',data=ad_data)
Out[14]:
<seaborn.axisgrid.JointGrid at 0x1c0e96c4470>

Create a jointplot showing the kde distributions of Daily Time spent on site vs. Age.

In [15]:
sns.jointplot(x='Age',y='Daily Time Spent on Site',data=ad_data,color='red',kind='kde');
C:\Anaconda3\lib\site-packages\statsmodels\nonparametric\kdetools.py:20: VisibleDeprecationWarning: using a non-integer number instead of an integer will result in an error in the future
  y = X[:m/2+1] + np.r_[0,X[m/2+1:],0]*1j
In [81]:
ad_data['Daily Time Spent on Site'].corr(ad_data['Daily Internet Usage'])
Out[81]:
0.51865847533718634

Create a jointplot of 'Daily Time Spent on Site' vs. 'Daily Internet Usage'

In [82]:
sns.jointplot(x='Daily Time Spent on Site',y='Daily Internet Usage',data=ad_data,color='green')
Out[82]:
<seaborn.axisgrid.JointGrid at 0x211837c1518>

Finally, create a pairplot with the hue defined by the 'Clicked on Ad' column feature.

In [83]:
sns.pairplot(ad_data,hue='Clicked on Ad',palette='bwr')
Out[83]:
<seaborn.axisgrid.PairGrid at 0x211839437f0>
In [16]:
ad_data.corr()
Out[16]:
Daily Time Spent on Site Area Income Age Daily Internet Usage Male Clicked on Ad
Daily Time Spent on Site 1.000000 0.310954 -0.331513 0.518658 -0.018951 -0.748117
Area Income 0.310954 1.000000 -0.182605 0.337496 0.001322 -0.476255
Age -0.331513 -0.182605 1.000000 -0.367209 -0.021044 0.492531
Daily Internet Usage 0.518658 0.337496 -0.367209 1.000000 0.028012 -0.786539
Male -0.018951 0.001322 -0.021044 0.028012 1.000000 -0.038027
Clicked on Ad -0.748117 -0.476255 0.492531 -0.786539 -0.038027 1.000000

Logistic Regression

Now it's time to do a train test split, and train our model!

You'll have the freedom here to choose columns that you want to train on!

Split the data into training set and testing set using train_test_split

In [17]:
from sklearn.model_selection import train_test_split
In [18]:
X = ad_data[['Daily Time Spent on Site', 'Age', 'Area Income','Daily Internet Usage', 'Male']]
y = ad_data['Clicked on Ad']
In [19]:
X_train, X_test, y_train, y_test = train_test_split(X, y, test_size=0.33, random_state=42)
In [20]:
X_train.info()
<class 'pandas.core.frame.DataFrame'>
Int64Index: 670 entries, 703 to 102
Data columns (total 5 columns):
Daily Time Spent on Site    670 non-null float64
Age                         670 non-null int64
Area Income                 670 non-null float64
Daily Internet Usage        670 non-null float64
Male                        670 non-null int64
dtypes: float64(3), int64(2)
memory usage: 31.4 KB
In [21]:
X_test.info()
<class 'pandas.core.frame.DataFrame'>
Int64Index: 330 entries, 521 to 133
Data columns (total 5 columns):
Daily Time Spent on Site    330 non-null float64
Age                         330 non-null int64
Area Income                 330 non-null float64
Daily Internet Usage        330 non-null float64
Male                        330 non-null int64
dtypes: float64(3), int64(2)
memory usage: 15.5 KB

Train and fit a logistic regression model on the training set.

In [22]:
from sklearn.linear_model import LogisticRegression
In [23]:
logmodel = LogisticRegression()
logmodel.fit(X_train,y_train)
Out[23]:
LogisticRegression(C=1.0, class_weight=None, dual=False, fit_intercept=True,
          intercept_scaling=1, max_iter=100, multi_class='ovr', n_jobs=1,
          penalty='l2', random_state=None, solver='liblinear', tol=0.0001,
          verbose=0, warm_start=False)

Predictions and Evaluations

Now predict values for the testing data.

In [24]:
predictions = logmodel.predict(X_test)

Create a classification report for the model.

In [25]:
from sklearn.metrics import classification_report
In [26]:
print(classification_report(y_test,predictions))
             precision    recall  f1-score   support

          0       0.87      0.96      0.91       162
          1       0.96      0.86      0.91       168

avg / total       0.91      0.91      0.91       330

Thanks!