Skip to content

Instantly share code, notes, and snippets.

@harisonmg
Created April 25, 2019 11:38
Show Gist options
  • Save harisonmg/af5e042b75b0f5e9b54083dee1d87358 to your computer and use it in GitHub Desktop.
Save harisonmg/af5e042b75b0f5e9b54083dee1d87358 to your computer and use it in GitHub Desktop.
Display the source blob
Display the rendered blob
Raw
{
"nbformat_minor": 1,
"cells": [
{
"source": "# Cluster Analysis Course Notebook",
"cell_type": "markdown",
"metadata": {
"collapsed": true
}
},
{
"source": "### Importing Data files",
"cell_type": "markdown",
"metadata": {}
},
{
"execution_count": 1,
"cell_type": "code",
"metadata": {},
"outputs": [
{
"execution_count": 1,
"metadata": {},
"data": {
"text/html": "<div>\n<style scoped>\n .dataframe tbody tr th:only-of-type {\n vertical-align: middle;\n }\n\n .dataframe tbody tr th {\n vertical-align: top;\n }\n\n .dataframe thead th {\n text-align: right;\n }\n</style>\n<table border=\"1\" class=\"dataframe\">\n <thead>\n <tr style=\"text-align: right;\">\n <th></th>\n <th>PRODUCT CODE</th>\n <th>PRODUCT CATEGORY</th>\n <th>UNIT LIST PRICE</th>\n </tr>\n </thead>\n <tbody>\n <tr>\n <th>0</th>\n <td>30001</td>\n <td>HEALTH &amp; BEAUTY</td>\n <td>$7.45</td>\n </tr>\n <tr>\n <th>1</th>\n <td>30002</td>\n <td>HEALTH &amp; BEAUTY</td>\n <td>$5.35</td>\n </tr>\n <tr>\n <th>2</th>\n <td>30003</td>\n <td>HEALTH &amp; BEAUTY</td>\n <td>$5.49</td>\n </tr>\n <tr>\n <th>3</th>\n <td>30004</td>\n <td>HEALTH &amp; BEAUTY</td>\n <td>$6.46</td>\n </tr>\n <tr>\n <th>4</th>\n <td>30005</td>\n <td>HEALTH &amp; BEAUTY</td>\n <td>$7.33</td>\n </tr>\n </tbody>\n</table>\n</div>",
"text/plain": " PRODUCT CODE PRODUCT CATEGORY UNIT LIST PRICE\n0 30001 HEALTH & BEAUTY $7.45 \n1 30002 HEALTH & BEAUTY $5.35 \n2 30003 HEALTH & BEAUTY $5.49 \n3 30004 HEALTH & BEAUTY $6.46 \n4 30005 HEALTH & BEAUTY $7.33 "
},
"output_type": "execute_result"
}
],
"source": "# The code was removed by Watson Studio for sharing."
},
{
"execution_count": 2,
"cell_type": "code",
"metadata": {},
"outputs": [
{
"execution_count": 2,
"metadata": {},
"data": {
"text/html": "<div>\n<style scoped>\n .dataframe tbody tr th:only-of-type {\n vertical-align: middle;\n }\n\n .dataframe tbody tr th {\n vertical-align: top;\n }\n\n .dataframe thead th {\n text-align: right;\n }\n</style>\n<table border=\"1\" class=\"dataframe\">\n <thead>\n <tr style=\"text-align: right;\">\n <th></th>\n <th>CUSTOMER NUM</th>\n <th>PRODUCT NUM</th>\n <th>QUANTITY PURCHASED</th>\n <th>DISCOUNT TAKEN</th>\n <th>TRANSACTION DATE</th>\n <th>STOCKOUT</th>\n </tr>\n </thead>\n <tbody>\n <tr>\n <th>0</th>\n <td>10114</td>\n <td>30011</td>\n <td>4</td>\n <td>0.0</td>\n <td>1/2/2015</td>\n <td>0</td>\n </tr>\n <tr>\n <th>1</th>\n <td>10217</td>\n <td>30016</td>\n <td>3</td>\n <td>0.0</td>\n <td>1/2/2015</td>\n <td>0</td>\n </tr>\n <tr>\n <th>2</th>\n <td>10224</td>\n <td>30013</td>\n <td>4</td>\n <td>0.0</td>\n <td>1/2/2015</td>\n <td>0</td>\n </tr>\n <tr>\n <th>3</th>\n <td>10103</td>\n <td>30012</td>\n <td>3</td>\n <td>0.2</td>\n <td>1/2/2015</td>\n <td>0</td>\n </tr>\n <tr>\n <th>4</th>\n <td>10037</td>\n <td>30010</td>\n <td>8</td>\n <td>0.0</td>\n <td>1/2/2015</td>\n <td>0</td>\n </tr>\n </tbody>\n</table>\n</div>",
"text/plain": " CUSTOMER NUM PRODUCT NUM QUANTITY PURCHASED DISCOUNT TAKEN \\\n0 10114 30011 4 0.0 \n1 10217 30016 3 0.0 \n2 10224 30013 4 0.0 \n3 10103 30012 3 0.2 \n4 10037 30010 8 0.0 \n\n TRANSACTION DATE STOCKOUT \n0 1/2/2015 0 \n1 1/2/2015 0 \n2 1/2/2015 0 \n3 1/2/2015 0 \n4 1/2/2015 0 "
},
"output_type": "execute_result"
}
],
"source": "#Import Transaction DataSet here\nbody = client_0b7f25d6f4c743e1bbf81e3ecac0de47.get_object(Bucket='ibmdnadatasciencelearningproject-donotdelete-pr-foj79k0orfi5wk',Key='DNA- Transaction Data Set - Student 3 of 3.csv')['Body']\n# add missing __iter__ method, so pandas accepts body as file-like object\nif not hasattr(body, \"__iter__\"): body.__iter__ = types.MethodType( __iter__, body )\n\ntransactions_data = pd.read_csv(body,sep='|')\ntransactions_data.head()\n"
},
{
"execution_count": 3,
"cell_type": "code",
"metadata": {},
"outputs": [
{
"execution_count": 3,
"metadata": {},
"data": {
"text/html": "<div>\n<style scoped>\n .dataframe tbody tr th:only-of-type {\n vertical-align: middle;\n }\n\n .dataframe tbody tr th {\n vertical-align: top;\n }\n\n .dataframe thead th {\n text-align: right;\n }\n</style>\n<table border=\"1\" class=\"dataframe\">\n <thead>\n <tr style=\"text-align: right;\">\n <th></th>\n <th>CUSTOMERID</th>\n <th>GENDER</th>\n <th>AGE</th>\n <th>INCOME</th>\n <th>EXPERIENCE SCORE</th>\n <th>LOYALTY GROUP</th>\n <th>ENROLLMENT DATE</th>\n <th>HOUSEHOLD SIZE</th>\n <th>MARITAL STATUS</th>\n </tr>\n </thead>\n <tbody>\n <tr>\n <th>0</th>\n <td>10001</td>\n <td>0</td>\n <td>64</td>\n <td>$133,498</td>\n <td>5</td>\n <td>enrolled</td>\n <td>06-03-2013</td>\n <td>4</td>\n <td>Single</td>\n </tr>\n <tr>\n <th>1</th>\n <td>10002</td>\n <td>0</td>\n <td>42</td>\n <td>$94,475</td>\n <td>9</td>\n <td>notenrolled</td>\n <td>NaN</td>\n <td>6</td>\n <td>Married</td>\n </tr>\n <tr>\n <th>2</th>\n <td>10003</td>\n <td>0</td>\n <td>40</td>\n <td>$88,610</td>\n <td>9</td>\n <td>enrolled</td>\n <td>02-09-2010</td>\n <td>5</td>\n <td>Married</td>\n </tr>\n <tr>\n <th>3</th>\n <td>10004</td>\n <td>0</td>\n <td>38</td>\n <td>$84,313</td>\n <td>8</td>\n <td>enrolled</td>\n <td>06-04-2015</td>\n <td>1</td>\n <td>Single</td>\n </tr>\n <tr>\n <th>4</th>\n <td>10005</td>\n <td>0</td>\n <td>30</td>\n <td>$51,498</td>\n <td>3</td>\n <td>notenrolled</td>\n <td>NaN</td>\n <td>1</td>\n <td>Single</td>\n </tr>\n </tbody>\n</table>\n</div>",
"text/plain": " CUSTOMERID GENDER AGE INCOME EXPERIENCE SCORE LOYALTY GROUP \\\n0 10001 0 64 $133,498 5 enrolled \n1 10002 0 42 $94,475 9 notenrolled \n2 10003 0 40 $88,610 9 enrolled \n3 10004 0 38 $84,313 8 enrolled \n4 10005 0 30 $51,498 3 notenrolled \n\n ENROLLMENT DATE HOUSEHOLD SIZE MARITAL STATUS \n0 06-03-2013 4 Single \n1 NaN 6 Married \n2 02-09-2010 5 Married \n3 06-04-2015 1 Single \n4 NaN 1 Single "
},
"output_type": "execute_result"
}
],
"source": "#Import Customer Dataset Here\nbody = client_0b7f25d6f4c743e1bbf81e3ecac0de47.get_object(Bucket='ibmdnadatasciencelearningproject-donotdelete-pr-foj79k0orfi5wk',Key='DNA - Customer Data Set - Student 1 of 3.csv')['Body']\n# add missing __iter__ method, so pandas accepts body as file-like object\nif not hasattr(body, \"__iter__\"): body.__iter__ = types.MethodType( __iter__, body )\n\ncustomer_data=pd.read_csv(body)\ncustomer_data.head()\n\n"
},
{
"source": "### Changing data types",
"cell_type": "markdown",
"metadata": {}
},
{
"execution_count": 4,
"cell_type": "code",
"metadata": {},
"outputs": [],
"source": "customer_data['INCOME']=customer_data['INCOME'].map(lambda x : x.replace('$',''))"
},
{
"execution_count": 5,
"cell_type": "code",
"metadata": {},
"outputs": [],
"source": "customer_data['INCOME']=customer_data['INCOME'].map(lambda x : int(x.replace(',','')))"
},
{
"source": "### Creating Customer View",
"cell_type": "markdown",
"metadata": {}
},
{
"execution_count": 6,
"cell_type": "code",
"metadata": {},
"outputs": [],
"source": "trans_products=transactions_data.merge(product_data,how='inner', left_on='PRODUCT NUM', right_on='PRODUCT CODE')"
},
{
"execution_count": 7,
"cell_type": "code",
"metadata": {},
"outputs": [],
"source": "trans_products['UNIT LIST PRICE']=trans_products['UNIT LIST PRICE'].map(lambda x : float(x.replace('$','')))"
},
{
"execution_count": 8,
"cell_type": "code",
"metadata": {},
"outputs": [],
"source": "trans_products['Total_Price']=trans_products['QUANTITY PURCHASED'] * trans_products['UNIT LIST PRICE'] * (1- trans_products['DISCOUNT TAKEN'])"
},
{
"execution_count": 9,
"cell_type": "code",
"metadata": {},
"outputs": [],
"source": "customer_prod_categ=trans_products.groupby(['CUSTOMER NUM','PRODUCT CATEGORY']).agg({'Total_Price':'sum'})"
},
{
"execution_count": 10,
"cell_type": "code",
"metadata": {},
"outputs": [],
"source": "customer_prod_categ=customer_prod_categ.reset_index()"
},
{
"execution_count": 11,
"cell_type": "code",
"metadata": {},
"outputs": [],
"source": "customer_pivot=customer_prod_categ.pivot(index='CUSTOMER NUM',columns='PRODUCT CATEGORY',values='Total_Price')"
},
{
"execution_count": 12,
"cell_type": "code",
"metadata": {},
"outputs": [],
"source": "trans_total_spend=trans_products.groupby('CUSTOMER NUM').agg({'Total_Price':'sum'}).\\\nrename(columns={'Total_Price':'TOTAL SPENT'})"
},
{
"execution_count": 13,
"cell_type": "code",
"metadata": {},
"outputs": [],
"source": "customer_KPIs=customer_pivot.merge(trans_total_spend,how='inner',left_index=True, right_index=True )"
},
{
"execution_count": 14,
"cell_type": "code",
"metadata": {},
"outputs": [],
"source": "customer_KPIs=customer_KPIs.fillna(0)\n"
},
{
"execution_count": 15,
"cell_type": "code",
"metadata": {},
"outputs": [],
"source": "customer_all_view=customer_data.merge(customer_KPIs,how='inner', left_on='CUSTOMERID', right_index=True)"
},
{
"execution_count": 16,
"cell_type": "code",
"metadata": {},
"outputs": [
{
"execution_count": 16,
"metadata": {},
"data": {
"text/html": "<div>\n<style scoped>\n .dataframe tbody tr th:only-of-type {\n vertical-align: middle;\n }\n\n .dataframe tbody tr th {\n vertical-align: top;\n }\n\n .dataframe thead th {\n text-align: right;\n }\n</style>\n<table border=\"1\" class=\"dataframe\">\n <thead>\n <tr style=\"text-align: right;\">\n <th></th>\n <th>CUSTOMERID</th>\n <th>GENDER</th>\n <th>AGE</th>\n <th>INCOME</th>\n <th>EXPERIENCE SCORE</th>\n <th>LOYALTY GROUP</th>\n <th>ENROLLMENT DATE</th>\n <th>HOUSEHOLD SIZE</th>\n <th>MARITAL STATUS</th>\n <th>APPAREL</th>\n <th>ELECTRONICS</th>\n <th>FOOD</th>\n <th>HEALTH &amp; BEAUTY</th>\n <th>TOTAL SPENT</th>\n </tr>\n </thead>\n <tbody>\n <tr>\n <th>0</th>\n <td>10001</td>\n <td>0</td>\n <td>64</td>\n <td>133498</td>\n <td>5</td>\n <td>enrolled</td>\n <td>06-03-2013</td>\n <td>4</td>\n <td>Single</td>\n <td>4022.430</td>\n <td>1601.315</td>\n <td>68.688</td>\n <td>1134.337</td>\n <td>6826.770</td>\n </tr>\n <tr>\n <th>1</th>\n <td>10002</td>\n <td>0</td>\n <td>42</td>\n <td>94475</td>\n <td>9</td>\n <td>notenrolled</td>\n <td>NaN</td>\n <td>6</td>\n <td>Married</td>\n <td>2312.509</td>\n <td>2473.163</td>\n <td>276.779</td>\n <td>0.000</td>\n <td>5062.451</td>\n </tr>\n <tr>\n <th>2</th>\n <td>10003</td>\n <td>0</td>\n <td>40</td>\n <td>88610</td>\n <td>9</td>\n <td>enrolled</td>\n <td>02-09-2010</td>\n <td>5</td>\n <td>Married</td>\n <td>2887.382</td>\n <td>5414.418</td>\n <td>260.640</td>\n <td>0.000</td>\n <td>8562.440</td>\n </tr>\n <tr>\n <th>3</th>\n <td>10004</td>\n <td>0</td>\n <td>38</td>\n <td>84313</td>\n <td>8</td>\n <td>enrolled</td>\n <td>06-04-2015</td>\n <td>1</td>\n <td>Single</td>\n <td>3637.213</td>\n <td>1840.211</td>\n <td>45.270</td>\n <td>0.000</td>\n <td>5522.694</td>\n </tr>\n <tr>\n <th>4</th>\n <td>10005</td>\n <td>0</td>\n <td>30</td>\n <td>51498</td>\n <td>3</td>\n <td>notenrolled</td>\n <td>NaN</td>\n <td>1</td>\n <td>Single</td>\n <td>213.512</td>\n <td>0.000</td>\n <td>0.000</td>\n <td>0.000</td>\n <td>213.512</td>\n </tr>\n </tbody>\n</table>\n</div>",
"text/plain": " CUSTOMERID GENDER AGE INCOME EXPERIENCE SCORE LOYALTY GROUP \\\n0 10001 0 64 133498 5 enrolled \n1 10002 0 42 94475 9 notenrolled \n2 10003 0 40 88610 9 enrolled \n3 10004 0 38 84313 8 enrolled \n4 10005 0 30 51498 3 notenrolled \n\n ENROLLMENT DATE HOUSEHOLD SIZE MARITAL STATUS APPAREL ELECTRONICS \\\n0 06-03-2013 4 Single 4022.430 1601.315 \n1 NaN 6 Married 2312.509 2473.163 \n2 02-09-2010 5 Married 2887.382 5414.418 \n3 06-04-2015 1 Single 3637.213 1840.211 \n4 NaN 1 Single 213.512 0.000 \n\n FOOD HEALTH & BEAUTY TOTAL SPENT \n0 68.688 1134.337 6826.770 \n1 276.779 0.000 5062.451 \n2 260.640 0.000 8562.440 \n3 45.270 0.000 5522.694 \n4 0.000 0.000 213.512 "
},
"output_type": "execute_result"
}
],
"source": "customer_all_view.head()"
},
{
"source": "# Clustering ",
"cell_type": "markdown",
"metadata": {}
},
{
"source": "_Step 1_",
"cell_type": "markdown",
"metadata": {}
},
{
"source": "Import the necessary libraries by using the following code: ",
"cell_type": "markdown",
"metadata": {}
},
{
"execution_count": 17,
"cell_type": "code",
"metadata": {},
"outputs": [],
"source": "from sklearn.cluster import KMeans\nfrom sklearn.cluster import AgglomerativeClustering"
},
{
"source": "_Step 2_",
"cell_type": "markdown",
"metadata": {}
},
{
"source": "Select the features on which you are clustering. In this example, we cluster \u201cincome\u201d and \u201cTotal spent\u201d variables by using the following code: ",
"cell_type": "markdown",
"metadata": {}
},
{
"execution_count": 18,
"cell_type": "code",
"metadata": {},
"outputs": [
{
"execution_count": 18,
"metadata": {},
"data": {
"text/html": "<div>\n<style scoped>\n .dataframe tbody tr th:only-of-type {\n vertical-align: middle;\n }\n\n .dataframe tbody tr th {\n vertical-align: top;\n }\n\n .dataframe thead th {\n text-align: right;\n }\n</style>\n<table border=\"1\" class=\"dataframe\">\n <thead>\n <tr style=\"text-align: right;\">\n <th></th>\n <th>INCOME</th>\n <th>TOTAL SPENT</th>\n </tr>\n </thead>\n <tbody>\n <tr>\n <th>0</th>\n <td>133498</td>\n <td>6826.770</td>\n </tr>\n <tr>\n <th>1</th>\n <td>94475</td>\n <td>5062.451</td>\n </tr>\n <tr>\n <th>2</th>\n <td>88610</td>\n <td>8562.440</td>\n </tr>\n <tr>\n <th>3</th>\n <td>84313</td>\n <td>5522.694</td>\n </tr>\n <tr>\n <th>4</th>\n <td>51498</td>\n <td>213.512</td>\n </tr>\n </tbody>\n</table>\n</div>",
"text/plain": " INCOME TOTAL SPENT\n0 133498 6826.770\n1 94475 5062.451\n2 88610 8562.440\n3 84313 5522.694\n4 51498 213.512"
},
"output_type": "execute_result"
}
],
"source": "cluster_input=customer_all_view[['INCOME','TOTAL SPENT']]\ncluster_input.head(5)"
},
{
"source": "The \u201ccluster_input\u201d variable is a Pandas data frame that contains only the columns \u201cincome\u201d and \u201ctotal spent\u201d. We use these two continuous variables because of the following reasons:\n\n Two variables can be easily visualized on a 2-dimensional plot\n Clustering algorithms rely on a distance function (like Euclidean distance) to compute similarity among data points. The sample space for categorical data is discrete and doesn\u2019t have a natural origin, so a Euclidean distance function on such a space isn\u2019t really meaningful.\n",
"cell_type": "markdown",
"metadata": {}
},
{
"source": "_Step 3_",
"cell_type": "markdown",
"metadata": {}
},
{
"source": "Initialize a K-means model with four clusters as follows: ",
"cell_type": "markdown",
"metadata": {}
},
{
"execution_count": 19,
"cell_type": "code",
"metadata": {},
"outputs": [],
"source": "Kmeans_model=KMeans(n_clusters=4)"
},
{
"source": "Although you can use the elbow method or silhouette to determine the optimal number of clusters, you and Retailer X agreed to divide their customer base into only four clusters. ",
"cell_type": "markdown",
"metadata": {}
},
{
"source": "_Step 4_",
"cell_type": "markdown",
"metadata": {}
},
{
"source": "Look at the parameters of the model by running the following code:\n",
"cell_type": "markdown",
"metadata": {}
},
{
"execution_count": 20,
"cell_type": "code",
"metadata": {},
"outputs": [
{
"execution_count": 20,
"metadata": {},
"data": {
"text/plain": "KMeans(algorithm='auto', copy_x=True, init='k-means++', max_iter=300,\n n_clusters=4, n_init=10, n_jobs=1, precompute_distances='auto',\n random_state=None, tol=0.0001, verbose=0)"
},
"output_type": "execute_result"
}
],
"source": "Kmeans_model"
},
{
"source": "The output shows the parameters that were passed to the model, which decide how the algorithm works because we passed only the number of cluster(k) parameter; every other parameter used its default value.\n\nThe K-means algorithm follows an iterative way for clustering data points. The number of iterations default value is 300, which is visible Out (23) output. This parameter defines the maximum iterative limit because the algorithm can reach convergence before reaching this maximum limit.",
"cell_type": "markdown",
"metadata": {}
},
{
"source": "_Step 5_",
"cell_type": "markdown",
"metadata": {}
},
{
"source": "Run the K-means cluster algorithm on the input by using \u201cfit_predict\u201d method:\n\n",
"cell_type": "markdown",
"metadata": {}
},
{
"execution_count": 21,
"cell_type": "code",
"metadata": {},
"outputs": [],
"source": "cluster_output = Kmeans_model.fit_predict(cluster_input)"
},
{
"source": "_Step 6_",
"cell_type": "markdown",
"metadata": {}
},
{
"source": "Get the output of the K-means algorithm by using the following code:\n\n",
"cell_type": "markdown",
"metadata": {}
},
{
"execution_count": 22,
"cell_type": "code",
"metadata": {},
"outputs": [
{
"execution_count": 22,
"metadata": {},
"data": {
"text/plain": "array([1, 3, 0, 0, 2, 1, 0, 3, 3, 0, 2, 3, 0, 0, 0, 0, 0, 3, 1, 0, 3, 3, 3,\n 2, 3, 3, 0, 2, 2, 1, 0, 2, 2, 3, 2, 2, 0, 3, 3, 2, 2, 0, 0, 0, 1, 2,\n 2, 0, 1, 2, 3, 2, 0, 2, 3, 2, 3, 3, 3, 2, 0, 3, 1, 3, 1, 0, 0, 3, 2,\n 0, 0, 2, 0, 0, 1, 2, 0, 2, 0, 1, 0, 3, 1, 3, 0, 3, 1, 2, 0, 2, 3, 1,\n 3, 3, 3, 0, 3, 2, 1, 3, 2, 2, 2, 2, 0, 3, 3, 2, 0, 2, 2, 2, 0, 2, 3,\n 2, 1, 1, 0, 0, 2, 3, 3, 2, 0, 0, 3, 0, 2, 1, 0, 0, 2, 0, 1, 3, 1, 1,\n 3, 0, 0, 2, 2, 2, 0, 3, 3, 2, 3, 0, 0, 3, 3, 3, 0, 3, 2, 2, 3, 2, 1,\n 2, 1, 3, 2, 0, 2, 1, 0, 2, 1, 2, 3, 3, 1, 2, 1, 1, 3, 2, 1, 2, 0, 2,\n 3, 1, 3, 3, 2, 1, 2, 3, 3, 1, 3, 1, 3, 1, 3, 0, 3, 2, 1, 1, 3, 2, 0,\n 1, 1, 1, 1, 2, 3, 0, 1, 3, 0, 3, 0, 2, 0, 2, 3, 2, 2, 0, 3, 2, 2, 0,\n 3, 0, 3, 0, 0, 2, 3, 1, 2, 2, 2, 0, 0, 0, 0, 2, 3, 3, 1, 2, 0, 3, 2,\n 3, 2, 0, 2, 1, 3, 3, 2, 1, 2, 0, 0, 1, 3, 0, 0, 3, 1, 0, 1, 2, 2, 2,\n 1, 0, 3, 3, 3, 0, 0, 0, 1, 0, 3, 0, 3, 1, 1, 2, 2, 1, 2, 2, 2, 2, 0,\n 0, 2, 0, 0, 1, 2, 1, 2, 2, 1, 2, 2, 3, 0, 0, 0, 0, 2, 1, 3, 0, 3, 0,\n 2, 0, 2, 0, 0, 2, 3, 2, 2, 3, 2, 0, 0, 2, 2, 3, 3, 3, 3, 1, 3, 0, 3,\n 3, 0, 1, 3, 0, 2, 0, 2, 3, 1, 1, 3, 0, 0, 3, 1, 3, 2, 3, 3, 2, 0, 3,\n 3, 0, 3, 0, 0, 1, 0, 1, 3, 0, 0, 3, 0, 2, 2, 2, 1, 0, 2, 0, 1, 2, 1,\n 2, 0, 1, 2, 3, 1, 0, 1, 0, 3, 1, 2, 0, 1, 0, 2, 1, 0, 0, 1, 3, 2, 0,\n 1, 2, 3, 3, 1, 2, 2, 3, 0, 0, 3, 0, 1, 3, 0, 2, 3, 0, 0, 2, 1, 0, 3,\n 3, 0, 3, 3, 2, 0, 1, 2, 0, 1, 2, 2, 0, 2, 2, 2, 2, 1, 0, 3, 3, 0, 2,\n 1, 0, 3, 0, 1, 3, 0, 2, 2, 3, 1, 0, 1, 3, 3, 0, 3, 0, 2, 2, 2, 1, 3,\n 1, 0, 2, 3, 2, 3, 1, 0, 0, 1, 0, 2, 3, 3, 3, 2, 0], dtype=int32)"
},
"output_type": "execute_result"
}
],
"source": "cluster_output"
},
{
"source": "_Step 7_",
"cell_type": "markdown",
"metadata": {}
},
{
"source": "The output of step 6 is in a NumPy array type. Run the following command to confirm that the output is in NumPy format and not Pandas. ",
"cell_type": "markdown",
"metadata": {}
},
{
"execution_count": 23,
"cell_type": "code",
"metadata": {},
"outputs": [
{
"execution_count": 23,
"metadata": {},
"data": {
"text/plain": "numpy.ndarray"
},
"output_type": "execute_result"
}
],
"source": "type(cluster_output)"
},
{
"source": "Recall that we used the Pandas data frame structure to store the tabular data that is in the CSV files (products, customers, and transactions). Let us look at the first few records of products by using the following code:\n\n",
"cell_type": "markdown",
"metadata": {}
},
{
"execution_count": 24,
"cell_type": "code",
"metadata": {},
"outputs": [
{
"execution_count": 24,
"metadata": {},
"data": {
"text/html": "<div>\n<style scoped>\n .dataframe tbody tr th:only-of-type {\n vertical-align: middle;\n }\n\n .dataframe tbody tr th {\n vertical-align: top;\n }\n\n .dataframe thead th {\n text-align: right;\n }\n</style>\n<table border=\"1\" class=\"dataframe\">\n <thead>\n <tr style=\"text-align: right;\">\n <th></th>\n <th>PRODUCT CODE</th>\n <th>PRODUCT CATEGORY</th>\n <th>UNIT LIST PRICE</th>\n </tr>\n </thead>\n <tbody>\n <tr>\n <th>0</th>\n <td>30001</td>\n <td>HEALTH &amp; BEAUTY</td>\n <td>$7.45</td>\n </tr>\n <tr>\n <th>1</th>\n <td>30002</td>\n <td>HEALTH &amp; BEAUTY</td>\n <td>$5.35</td>\n </tr>\n <tr>\n <th>2</th>\n <td>30003</td>\n <td>HEALTH &amp; BEAUTY</td>\n <td>$5.49</td>\n </tr>\n <tr>\n <th>3</th>\n <td>30004</td>\n <td>HEALTH &amp; BEAUTY</td>\n <td>$6.46</td>\n </tr>\n <tr>\n <th>4</th>\n <td>30005</td>\n <td>HEALTH &amp; BEAUTY</td>\n <td>$7.33</td>\n </tr>\n </tbody>\n</table>\n</div>",
"text/plain": " PRODUCT CODE PRODUCT CATEGORY UNIT LIST PRICE\n0 30001 HEALTH & BEAUTY $7.45 \n1 30002 HEALTH & BEAUTY $5.35 \n2 30003 HEALTH & BEAUTY $5.49 \n3 30004 HEALTH & BEAUTY $6.46 \n4 30005 HEALTH & BEAUTY $7.33 "
},
"output_type": "execute_result"
}
],
"source": "product_data.head()"
},
{
"source": " If you run the values method on a Pandas dataframe, it will convert it to Numpy. Run it on Product Pandas and observe the output. ",
"cell_type": "markdown",
"metadata": {}
},
{
"execution_count": null,
"cell_type": "code",
"metadata": {},
"outputs": [],
"source": "product_data.head().values"
},
{
"source": "To access particular elements in that array, you use square brackets ([]) to index array values\n\nFor example, if you need to know the value represented by Row 1 (second row) and column 2 (third column), You should use the index [1,2]\n\nTo access the element in the second row and third column, use the following code:",
"cell_type": "markdown",
"metadata": {}
},
{
"execution_count": 26,
"cell_type": "code",
"metadata": {},
"outputs": [
{
"execution_count": 26,
"metadata": {},
"data": {
"text/plain": "' $5.35 '"
},
"output_type": "execute_result"
}
],
"source": "product_data.head().values[1,2]"
},
{
"source": "To view all elements presented in the first row, use \u201c:\u201d for the column index to call all columns\n\n",
"cell_type": "markdown",
"metadata": {}
},
{
"execution_count": 27,
"cell_type": "code",
"metadata": {},
"outputs": [
{
"execution_count": 27,
"metadata": {},
"data": {
"text/plain": "array([30002, 'HEALTH & BEAUTY', ' $5.35 '], dtype=object)"
},
"output_type": "execute_result"
}
],
"source": "product_data.head().values[1,:]"
},
{
"source": "Values in the output are presented in a 1-Dimensional array, since we only called a single row of data\n\nTo view the values of the third column, use the following code:\n\n",
"cell_type": "markdown",
"metadata": {}
},
{
"execution_count": 28,
"cell_type": "code",
"metadata": {},
"outputs": [
{
"execution_count": 28,
"metadata": {},
"data": {
"text/plain": "array([' $7.45 ', ' $5.35 ', ' $5.49 ', ' $6.46 ', ' $7.33 '], dtype=object)"
},
"output_type": "execute_result"
}
],
"source": "product_data.head().values[:,2]"
},
{
"source": "Values in the output are presented in a 1-dimensional array because we called only a single column of data.\n\nYou can convert the 1-dimensional NumPy array to a Pandas data frame by using the following code:",
"cell_type": "markdown",
"metadata": {}
},
{
"execution_count": 29,
"cell_type": "code",
"metadata": {},
"outputs": [],
"source": "cluster_output_pd=pd.DataFrame(cluster_output,columns=['segment'])"
},
{
"source": "The \u201ccluster_output\u201d is a 1-dimensional array because a single cluster index is assigned to every customer record.\n\nVerify that \u201ccluster_output_pd\u201d is a Pandas data frame with a single column called \u201csegment\u201d by using the following code:",
"cell_type": "markdown",
"metadata": {}
},
{
"execution_count": 30,
"cell_type": "code",
"metadata": {},
"outputs": [
{
"execution_count": 30,
"metadata": {},
"data": {
"text/html": "<div>\n<style scoped>\n .dataframe tbody tr th:only-of-type {\n vertical-align: middle;\n }\n\n .dataframe tbody tr th {\n vertical-align: top;\n }\n\n .dataframe thead th {\n text-align: right;\n }\n</style>\n<table border=\"1\" class=\"dataframe\">\n <thead>\n <tr style=\"text-align: right;\">\n <th></th>\n <th>segment</th>\n </tr>\n </thead>\n <tbody>\n <tr>\n <th>0</th>\n <td>1</td>\n </tr>\n <tr>\n <th>1</th>\n <td>3</td>\n </tr>\n <tr>\n <th>2</th>\n <td>0</td>\n </tr>\n <tr>\n <th>3</th>\n <td>0</td>\n </tr>\n <tr>\n <th>4</th>\n <td>2</td>\n </tr>\n </tbody>\n</table>\n</div>",
"text/plain": " segment\n0 1\n1 3\n2 0\n3 0\n4 2"
},
"output_type": "execute_result"
}
],
"source": "cluster_output_pd.head()"
},
{
"source": "_Step 8_",
"cell_type": "markdown",
"metadata": {}
},
{
"source": "Merge the cluster input containing the income and total spending for each customer and the cluster output, which contains the cluster index, by using the following code:",
"cell_type": "markdown",
"metadata": {}
},
{
"execution_count": 31,
"cell_type": "code",
"metadata": {},
"outputs": [],
"source": "segment_DF=pd.concat([cluster_input,cluster_output_pd],axis=1)"
},
{
"source": "_Step 9_",
"cell_type": "markdown",
"metadata": {}
},
{
"source": "Verify output using the following command",
"cell_type": "markdown",
"metadata": {}
},
{
"execution_count": 32,
"cell_type": "code",
"metadata": {},
"outputs": [
{
"execution_count": 32,
"metadata": {},
"data": {
"text/html": "<div>\n<style scoped>\n .dataframe tbody tr th:only-of-type {\n vertical-align: middle;\n }\n\n .dataframe tbody tr th {\n vertical-align: top;\n }\n\n .dataframe thead th {\n text-align: right;\n }\n</style>\n<table border=\"1\" class=\"dataframe\">\n <thead>\n <tr style=\"text-align: right;\">\n <th></th>\n <th>INCOME</th>\n <th>TOTAL SPENT</th>\n <th>segment</th>\n </tr>\n </thead>\n <tbody>\n <tr>\n <th>0</th>\n <td>133498</td>\n <td>6826.770</td>\n <td>1</td>\n </tr>\n <tr>\n <th>1</th>\n <td>94475</td>\n <td>5062.451</td>\n <td>3</td>\n </tr>\n <tr>\n <th>2</th>\n <td>88610</td>\n <td>8562.440</td>\n <td>0</td>\n </tr>\n <tr>\n <th>3</th>\n <td>84313</td>\n <td>5522.694</td>\n <td>0</td>\n </tr>\n <tr>\n <th>4</th>\n <td>51498</td>\n <td>213.512</td>\n <td>2</td>\n </tr>\n </tbody>\n</table>\n</div>",
"text/plain": " INCOME TOTAL SPENT segment\n0 133498 6826.770 1\n1 94475 5062.451 3\n2 88610 8562.440 0\n3 84313 5522.694 0\n4 51498 213.512 2"
},
"output_type": "execute_result"
}
],
"source": "segment_DF.head()"
},
{
"source": "_Step 10_",
"cell_type": "markdown",
"metadata": {}
},
{
"source": "The cluster centroids that are computed by the algorithm can be found by using a method that is called \u201ccluster_centers\u201d. Apply the method to the K-means model by using the following code:",
"cell_type": "markdown",
"metadata": {}
},
{
"execution_count": 33,
"cell_type": "code",
"metadata": {},
"outputs": [
{
"execution_count": 33,
"metadata": {},
"data": {
"text/plain": "array([[ 76337.14084507, 5260.48642958],\n [ 138471.625 , 6972.91513636],\n [ 38530.82608696, 2260.43836232],\n [ 110254.62121212, 7744.12999242]])"
},
"output_type": "execute_result"
}
],
"source": "Kmeans_model.cluster_centers_"
},
{
"source": "_Step 11_",
"cell_type": "markdown",
"metadata": {}
},
{
"source": "The \u201csegment_DF\u201d Pandas data frame that is created in step 8 contains points that belong to all customer segments. To select only those segments that belong to the first cluster (cluster index=0), use the following code:",
"cell_type": "markdown",
"metadata": {}
},
{
"execution_count": 34,
"cell_type": "code",
"metadata": {},
"outputs": [
{
"execution_count": 34,
"metadata": {},
"data": {
"text/html": "<div>\n<style scoped>\n .dataframe tbody tr th:only-of-type {\n vertical-align: middle;\n }\n\n .dataframe tbody tr th {\n vertical-align: top;\n }\n\n .dataframe thead th {\n text-align: right;\n }\n</style>\n<table border=\"1\" class=\"dataframe\">\n <thead>\n <tr style=\"text-align: right;\">\n <th></th>\n <th>INCOME</th>\n <th>TOTAL SPENT</th>\n <th>segment</th>\n </tr>\n </thead>\n <tbody>\n <tr>\n <th>2</th>\n <td>88610</td>\n <td>8562.440</td>\n <td>0</td>\n </tr>\n <tr>\n <th>3</th>\n <td>84313</td>\n <td>5522.694</td>\n <td>0</td>\n </tr>\n <tr>\n <th>6</th>\n <td>65002</td>\n <td>5224.616</td>\n <td>0</td>\n </tr>\n <tr>\n <th>9</th>\n <td>76994</td>\n <td>6620.147</td>\n <td>0</td>\n </tr>\n <tr>\n <th>12</th>\n <td>88829</td>\n <td>4685.902</td>\n <td>0</td>\n </tr>\n </tbody>\n</table>\n</div>",
"text/plain": " INCOME TOTAL SPENT segment\n2 88610 8562.440 0\n3 84313 5522.694 0\n6 65002 5224.616 0\n9 76994 6620.147 0\n12 88829 4685.902 0"
},
"output_type": "execute_result"
}
],
"source": "segment_DF[segment_DF.segment==0].head()"
},
{
"source": "Condition \u201csegment==0\u201d selects only those assigned to the first cluster. Similarly, you can do the same for other clusters ",
"cell_type": "markdown",
"metadata": {}
},
{
"source": "_Step 12_",
"cell_type": "markdown",
"metadata": {}
},
{
"source": "Plot the clustering results. First, import the plotting library by using the following code:",
"cell_type": "markdown",
"metadata": {}
},
{
"execution_count": 35,
"cell_type": "code",
"metadata": {},
"outputs": [],
"source": "import matplotlib.pyplot as plt"
},
{
"source": "_Step 13_",
"cell_type": "markdown",
"metadata": {}
},
{
"source": "Use the filter condition that was applied in step 10 to select only those customers that belong to the first cluster. Plot their income and age in purple. Select the second cluster and plot their income and age in blue. Repeat for clusters 3 and 4. Plot the cluster centroids that you have computed in step 9. ",
"cell_type": "markdown",
"metadata": {}
},
{
"execution_count": 36,
"cell_type": "code",
"metadata": {},
"outputs": [
{
"output_type": "display_data",
"data": {
"image/png": "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\n",
"text/plain": "<matplotlib.figure.Figure at 0x7fe7b4eeccc0>"
},
"metadata": {}
}
],
"source": "\nplt.scatter(segment_DF[segment_DF.segment==0]['INCOME'],segment_DF[segment_DF.segment==0]['TOTAL SPENT'],s=50, c='purple',label='Cluster1')\n\nplt.scatter(segment_DF[segment_DF.segment==1]['INCOME'],segment_DF[segment_DF.segment==1]['TOTAL SPENT'],s=50, c='blue',label='Cluster3')\n\nplt.scatter(segment_DF[segment_DF.segment==2]['INCOME'],segment_DF[segment_DF.segment==2]['TOTAL SPENT'],s=50, c='green',label='Cluster4')\n\nplt.scatter(segment_DF[segment_DF.segment==3]['INCOME'],segment_DF[segment_DF.segment==3]['TOTAL SPENT'],s=50, c='cyan',label='Cluster2')\n\nplt.scatter(Kmeans_model.cluster_centers_[:,0], Kmeans_model.cluster_centers_[:,1],s=200,marker='s', c='red', alpha=0.7, label='Centroids')\n\nplt.title('Customer segments using K-means (k=4)')\n\nplt.xlabel('Income')\n\nplt.ylabel('Total Spend')\n\nplt.legend()\n\nplt.show()\n"
},
{
"source": "_Step 14_",
"cell_type": "markdown",
"metadata": {}
},
{
"source": "Using the graph that was produced in step 12, create a table to describe the four customer segments relative to their income and spend.",
"cell_type": "markdown",
"metadata": {}
},
{
"source": "_Step 15_",
"cell_type": "markdown",
"metadata": {}
},
{
"source": "Retailer X must know all about the different customer segments demographics. So, you must discover the characteristics that are associated with each segment, such as the age group, household size, and loyalty enrolment. To do this task, group by each customer segment and calculate group measures such as average age, percentage of loyalty enrolment, and median of house hold size.\n\nMerge the clustering output with the customer all view by using the following code:",
"cell_type": "markdown",
"metadata": {}
},
{
"execution_count": 37,
"cell_type": "code",
"metadata": {},
"outputs": [
{
"execution_count": 37,
"metadata": {},
"data": {
"text/html": "<div>\n<style scoped>\n .dataframe tbody tr th:only-of-type {\n vertical-align: middle;\n }\n\n .dataframe tbody tr th {\n vertical-align: top;\n }\n\n .dataframe thead th {\n text-align: right;\n }\n</style>\n<table border=\"1\" class=\"dataframe\">\n <thead>\n <tr style=\"text-align: right;\">\n <th></th>\n <th>CUSTOMERID</th>\n <th>GENDER</th>\n <th>AGE</th>\n <th>INCOME</th>\n <th>EXPERIENCE SCORE</th>\n <th>LOYALTY GROUP</th>\n <th>ENROLLMENT DATE</th>\n <th>HOUSEHOLD SIZE</th>\n <th>MARITAL STATUS</th>\n <th>APPAREL</th>\n <th>ELECTRONICS</th>\n <th>FOOD</th>\n <th>HEALTH &amp; BEAUTY</th>\n <th>TOTAL SPENT</th>\n <th>segment</th>\n </tr>\n </thead>\n <tbody>\n <tr>\n <th>0</th>\n <td>10001</td>\n <td>0</td>\n <td>64</td>\n <td>133498</td>\n <td>5</td>\n <td>enrolled</td>\n <td>06-03-2013</td>\n <td>4</td>\n <td>Single</td>\n <td>4022.430</td>\n <td>1601.315</td>\n <td>68.688</td>\n <td>1134.337</td>\n <td>6826.770</td>\n <td>1</td>\n </tr>\n <tr>\n <th>1</th>\n <td>10002</td>\n <td>0</td>\n <td>42</td>\n <td>94475</td>\n <td>9</td>\n <td>notenrolled</td>\n <td>NaN</td>\n <td>6</td>\n <td>Married</td>\n <td>2312.509</td>\n <td>2473.163</td>\n <td>276.779</td>\n <td>0.000</td>\n <td>5062.451</td>\n <td>3</td>\n </tr>\n <tr>\n <th>2</th>\n <td>10003</td>\n <td>0</td>\n <td>40</td>\n <td>88610</td>\n <td>9</td>\n <td>enrolled</td>\n <td>02-09-2010</td>\n <td>5</td>\n <td>Married</td>\n <td>2887.382</td>\n <td>5414.418</td>\n <td>260.640</td>\n <td>0.000</td>\n <td>8562.440</td>\n <td>0</td>\n </tr>\n <tr>\n <th>3</th>\n <td>10004</td>\n <td>0</td>\n <td>38</td>\n <td>84313</td>\n <td>8</td>\n <td>enrolled</td>\n <td>06-04-2015</td>\n <td>1</td>\n <td>Single</td>\n <td>3637.213</td>\n <td>1840.211</td>\n <td>45.270</td>\n <td>0.000</td>\n <td>5522.694</td>\n <td>0</td>\n </tr>\n <tr>\n <th>4</th>\n <td>10005</td>\n <td>0</td>\n <td>30</td>\n <td>51498</td>\n <td>3</td>\n <td>notenrolled</td>\n <td>NaN</td>\n <td>1</td>\n <td>Single</td>\n <td>213.512</td>\n <td>0.000</td>\n <td>0.000</td>\n <td>0.000</td>\n <td>213.512</td>\n <td>2</td>\n </tr>\n </tbody>\n</table>\n</div>",
"text/plain": " CUSTOMERID GENDER AGE INCOME EXPERIENCE SCORE LOYALTY GROUP \\\n0 10001 0 64 133498 5 enrolled \n1 10002 0 42 94475 9 notenrolled \n2 10003 0 40 88610 9 enrolled \n3 10004 0 38 84313 8 enrolled \n4 10005 0 30 51498 3 notenrolled \n\n ENROLLMENT DATE HOUSEHOLD SIZE MARITAL STATUS APPAREL ELECTRONICS \\\n0 06-03-2013 4 Single 4022.430 1601.315 \n1 NaN 6 Married 2312.509 2473.163 \n2 02-09-2010 5 Married 2887.382 5414.418 \n3 06-04-2015 1 Single 3637.213 1840.211 \n4 NaN 1 Single 213.512 0.000 \n\n FOOD HEALTH & BEAUTY TOTAL SPENT segment \n0 68.688 1134.337 6826.770 1 \n1 276.779 0.000 5062.451 3 \n2 260.640 0.000 8562.440 0 \n3 45.270 0.000 5522.694 0 \n4 0.000 0.000 213.512 2 "
},
"output_type": "execute_result"
}
],
"source": "customer_demographics=pd.concat([customer_all_view,cluster_output_pd],axis=1)\ncustomer_demographics.head()\n"
},
{
"source": "This output shows the mean age and median household size for each cluster. Notice how age varies significantly across segments.\n\nWith regards to loyalty enrolment, you must calculate the percentage of participation by using the following formula:\n\nSo, you create a function by the name \u201cpercent_loyalty\u201d by using the following code: ",
"cell_type": "markdown",
"metadata": {}
},
{
"execution_count": 38,
"cell_type": "code",
"metadata": {},
"outputs": [],
"source": "def percent_loyalty(series):\n percent=100 * series.value_counts()['enrolled'] /series.count()\n return percent"
},
{
"source": "This function accepts the Pandas series as input, which is the series that we are going to pass as the \u201cloyalty group\u201d column (one Pandas data frame column is a Pandas series). The function returns the percentage of enrolment by calculating the number of enrolled customers (by using the value_counts method) to the total number of customers (by using the count function).\n\nPass the created function as an aggregate measure in the \u201cagg\u201d command as follows:",
"cell_type": "markdown",
"metadata": {}
},
{
"execution_count": 39,
"cell_type": "code",
"metadata": {},
"outputs": [
{
"execution_count": 39,
"metadata": {},
"data": {
"text/html": "<div>\n<style scoped>\n .dataframe tbody tr th:only-of-type {\n vertical-align: middle;\n }\n\n .dataframe tbody tr th {\n vertical-align: top;\n }\n\n .dataframe thead th {\n text-align: right;\n }\n</style>\n<table border=\"1\" class=\"dataframe\">\n <thead>\n <tr style=\"text-align: right;\">\n <th></th>\n <th>LOYALTY GROUP</th>\n <th>HOUSEHOLD SIZE</th>\n <th>AGE</th>\n </tr>\n <tr>\n <th>segment</th>\n <th></th>\n <th></th>\n <th></th>\n </tr>\n </thead>\n <tbody>\n <tr>\n <th>0</th>\n <td>32.394366</td>\n <td>3</td>\n <td>35.661972</td>\n </tr>\n <tr>\n <th>1</th>\n <td>65.909091</td>\n <td>2</td>\n <td>73.420455</td>\n </tr>\n <tr>\n <th>2</th>\n <td>52.173913</td>\n <td>2</td>\n <td>24.449275</td>\n </tr>\n <tr>\n <th>3</th>\n <td>66.666667</td>\n <td>3</td>\n <td>47.416667</td>\n </tr>\n </tbody>\n</table>\n</div>",
"text/plain": " LOYALTY GROUP HOUSEHOLD SIZE AGE\nsegment \n0 32.394366 3 35.661972\n1 65.909091 2 73.420455\n2 52.173913 2 24.449275\n3 66.666667 3 47.416667"
},
"output_type": "execute_result"
}
],
"source": "customer_demographics.groupby('segment').agg({'AGE':'mean','HOUSEHOLD SIZE':'median','LOYALTY GROUP': percent_loyalty})"
},
{
"source": "Extend the tabular report that you constructed in step 15 to include the segment demographic data you produced\n\nThis table shows the demographic segmentation for Retailer X customer segments.\nDemographic segmentation for Retailer X customer segments\n",
"cell_type": "markdown",
"metadata": {}
},
{
"source": "THE END!",
"cell_type": "markdown",
"metadata": {}
},
{
"source": "#### Harison Mwangi",
"cell_type": "markdown",
"metadata": {}
},
{
"source": "https://www.linkedin.com/in/harison-m-418641102",
"cell_type": "markdown",
"metadata": {}
}
],
"metadata": {
"kernelspec": {
"display_name": "Python 3.5",
"name": "python3",
"language": "python"
},
"language_info": {
"mimetype": "text/x-python",
"nbconvert_exporter": "python",
"version": "3.5.5",
"name": "python",
"file_extension": ".py",
"pygments_lexer": "ipython3",
"codemirror_mode": {
"version": 3,
"name": "ipython"
}
}
},
"nbformat": 4
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment