Customer Shopping Analysis

nhtram911

Introduction

This is my personal project, use dataset from Kaggle.com to practice Python skills, data visualization and business knowledge.

Link Kaggle: https://www.kaggle.com/code/trmnguynhi/customer-shopping-analysis

Business case

The dataset offers a comprehensive view of consumer shopping trends, aiming to uncover patterns and behaviors in retail purchasing. It contains detailed transactional data across various product categories, customer demographics, and purchase channels. Key features may include:

  • Transaction Details: Purchase date, transaction value, product category, and payment method.
  • Customer Information: Age group, gender, location, and loyalty status.
  • Shopping Behavior: Frequency of purchases, average spend per transaction, and seasonal trends.

This analysis will contain three steps as below:

  • Data Preparation
  • Data Exploration
  • Data Analysis & Insights

Data Preparation

import pandas as pd
import matplotlib.pyplot as plt
import numpy as np
import plotly.express as px
import seaborn as sns
shopping_data = pd.read_csv("/kaggle/input/customer-shopping-latest-trends-dataset/shopping_trends.csv")

Data Exploration

shopping_data.info()

shopping_data.describe()
shopping_data.head(10)

Data Analysis

I. Customer Segment

1. Geographic

customer_by_location = shopping_data.groupby("Location").agg({"Customer ID":"count"}).reset_index() state_name_to_code = { 'Alabama': 'AL', 'Alaska': 'AK', 'Arizona': 'AZ', 'Arkansas': 'AR', 'California': 'CA'
                      , 'Colorado': 'CO', 'Connecticut': 'CT', 'Delaware': 'DE', 'Florida': 'FL', 'Georgia': 'GA'
                      , 'Hawaii': 'HI', 'Idaho': 'ID', 'Illinois': 'IL', 'Indiana': 'IN', 'Iowa': 'IA'
                      , 'Kansas': 'KS', 'Kentucky': 'KY', 'Louisiana': 'LA', 'Maine': 'ME', 'Maryland': 'MD'
                      , 'Massachusetts': 'MA', 'Michigan': 'MI', 'Minnesota': 'MN', 'Mississippi': 'MS', 'Missouri': 'MO'
                      , 'Montana': 'MT', 'Nebraska': 'NE', 'Nevada': 'NV', 'New Hampshire': 'NH', 'New Jersey': 'NJ', 'New Mexico': 'NM'
                      , 'New York': 'NY', 'North Carolina': 'NC', 'North Dakota': 'ND', 'Ohio': 'OH', 'Oklahoma': 'OK', 'Oregon': 'OR'
                      , 'Pennsylvania': 'PA', 'Rhode Island': 'RI', 'South Carolina': 'SC', 'South Dakota': 'SD', 'Tennessee': 'TN'
                      , 'Texas': 'TX', 'Utah': 'UT', 'Vermont': 'VT', 'Virginia': 'VA', 'Washington': 'WA', 'West Virginia': 'WV'
                      , 'Wisconsin': 'WI', 'Wyoming': 'WY' }
customer_by_location['Location code']= customer_by_location['Location'].map(state_name_to_code)

fig = px.choropleth(customer_by_location, locationmode='USA-states',locations= 'Location code'
, color = "Customer ID"
, color_continuous_scale= 'viridis_r'
, hover_data= {'Location': True, 'Location code': False}
, labels={'Location':'State name','Customer ID': 'Number of Customers'}
, scope='usa'
, title = 'Number of Customers by Location'
)

fig.show()

puramt_by_location = shopping_data.groupby("Location").agg({"Purchase Amount (USD)":"mean"}).reset_index()
puramt_by_location['Location code']= puramt_by_location['Location'].map(state_name_to_code)
px.choropleth(puramt_by_location, locationmode='USA-states',locations= 'Location code'
, color = "Purchase Amount (USD)"
, color_continuous_scale= 'viridis_r'
, hover_data= {'Location': True, 'Location code': False}
, labels={'Location':'State name','Purchase Amount (USD)': 'Total Purchase Amt (USD)'}
, scope='usa'
, title = 'Purchase Amt by Location'
)

From the map, the number of customers distributes more densely in the West of USA (California and Montana). However, regarding the total purchase amount, Alaska, Arizona and Pennsylvania accounts for the highest amount.

2. Demographic

2.1 Gender

data_by_gender = shopping_data.groupby("Gender").agg(Customer_Count=("Customer ID", "count")
, Total_Purchase_Amount=("Purchase Amount (USD)", "sum")
, Average_Purchase_Amount=("Purchase Amount (USD)", "mean")).reset_index()
data_by_gender

fig, ax = plt.subplots(1,2)
colors = ['#ff69b4','#1f77b4']
ax[0].pie(data_by_gender['Customer_Count'], labels= data_by_gender['Gender'], colors = colors, autopct='%.0f%%')
ax[0].set_title('Customer Distribution by Gender', size =10)

ax[1].pie(data_by_gender['Total_Purchase_Amount'], labels= data_by_gender['Gender'], colors = colors, autopct='%.0f%%')
ax[1].set_title('Purchase Amount by Gender', size =10)

The number of male customers is double that of female customers, but their average purchase amount is nearly the same.

frequency_of_purchases = shopping_data.groupby(['Gender','Frequency of Purchases']).agg(Count = ('Frequency of Purchases','count')).reset_index()
frequency_of_purchases_female = frequency_of_purchases[frequency_of_purchases['Gender']=='Female']
frequency_of_purchases_male = frequency_of_purchases[frequency_of_purchases['Gender']=='Male']
fig,ax=plt.subplots(1,2)
ax[0].pie(frequency_of_purchases_female['Count'],labels= frequency_of_purchases_female['Frequency of Purchases']
, autopct='%.0f%%', textprops={'fontsize': 7})
ax[0].set_title("Female", size =10)
ax[1].pie(frequency_of_purchases_male['Count'],labels= frequency_of_purchases_male['Frequency of Purchases']
, autopct='%.0f%%', textprops={'fontsize': 7})
ax[1].set_title("Male", size =10)
fig.suptitle('Purchase Frequency by Gender', fontsize=10)
plt.subplots_adjust(wspace=0.8, top=1.2)

The frequency of purchase distribution is nearly the same between each groups, and between male and female.

color_by_gender = shopping_data.groupby(['Gender','Color']).agg(Count=('Color','count')).reset_index()
color_by_gender_female = color_by_gender[color_by_gender['Gender']=='Female']
color_by_gender_male = color_by_gender[color_by_gender['Gender']=='Male']
color_by_gender_female = color_by_gender_female.sort_values(by='Count', ascending= False).head(5)
color_by_gender_male = color_by_gender_male.sort_values(by='Count', ascending= False).head(5)
palette1 = color_by_gender_female['Color'].tolist()
palette2 = color_by_gender_male['Color'].tolist()
fig, ax = plt.subplots(1,2, figsize = (7,3))
sns.barplot(color_by_gender_female, y= 'Color', x= 'Count', palette= palette1,ax= ax[0])
ax[0].set_title('Female')
sns.barplot(color_by_gender_male, y= 'Color', x= 'Count', palette= palette2,ax= ax[1])
ax[1].set_title('Male')
plt.subplots_adjust(wspace=0.5, top =0.8)
plt.suptitle('Top 5 Most Favorite Color by Gender')

Women tend to like vibrant colors, while men prefer more muted colors.

2.2 Age:

I divide Age into 6 groups for analysis

shopping_data['Age_Group']=['18 to 20' if i<=20 else
'21 to 30' if i<=30 else
'31 to 40' if i <=40 else
'41 to 50' if i <=50 else
'51 to 60' if i <=60 else
'61 to 70' for i in shopping_data['Age']]
age_distribution = shopping_data.groupby('Age_Group').agg(NumberofCustomer = ('Age_Group','count'),Avg_Purchase_Amount=("Purchase Amount (USD)", "mean")).reset_index()
fig, ax = plt.subplots()
sns.barplot(age_distribution, x = 'Age_Group', y= 'NumberofCustomer', ax= ax)
ax2 = ax.twinx()
sns.lineplot(age_distribution, x = 'Age_Group', y= 'Avg_Purchase_Amount',color = 'black', ax= ax2 )
ax.set_xlabel('Age Group')
ax.set_ylabel('Number of Customers')
ax2.set_ylabel('Average Purchase Amount (USD)')

Age Group from 21 to 30, which the a group that has the most stable income and is in comfortable finance

payment_method_by_age = shopping_data.groupby(['Age_Group','Payment Method']).agg(Count = ('Payment Method','count')).reset_index()
sns.barplot(payment_method_by_age, x = 'Age_Group', y= 'Count', hue= 'Payment Method')
plt.legend(loc='center left', bbox_to_anchor=(1, 0.5))

Cash is most used for Age Group below 20 and above 51, who are less have connection with technology than others. Most of group prefer using Credit Card than Debit Card.

shipping_type_by_age = shopping_data.groupby(['Age_Group','Shipping Type']).agg(Count = ('Customer ID','count')).reset_index()
# shipping_type_by_age
fig,ax = plt.subplots(3,2, figsize=(20, 14))
ax = ax.flatten()
for i, age_group in enumerate(shipping_type_by_age['Age_Group'].unique()):
   age_data = shipping_type_by_age[shipping_type_by_age['Age_Group'] == age_group]
   ax[i].pie(age_data['Count'], labels=age_data['Shipping Type'], autopct='%.0f%%', textprops= {'fontsize': 8})
   ax[i].set_title(f'Age Group: {age_group}')

plt.tight_layout()

II. Product Categories

Color & Season

color_by_season = shopping_data.groupby(['Season','Color']).agg(TotalCustomer = ('Customer ID', 'count') ).reset_index()
top_colors = color_by_season.groupby('Season').apply(lambda x: x.nlargest(3, 'TotalCustomer')).reset_index(drop=True)
top_colors

prefered_size = shopping_data['Size'].value_counts().reset_index()
prefered_size.columns = ['Size', 'Count']
sns.barplot(prefered_size, x= 'Size', y = 'Count')

Based on favourite colors of each season, we can develop strategies to make products with those colors to boost sales. Based on prefered size, company can arrange the product line to avoid out of stock

Review Rating & Categories

rating_by_cat = shopping_data.groupby(['Category']).agg(AvgRating= ('Review Rating','mean')).reset_index()

Promo Used and Discount Applied

promo_used = shopping_data['Promo Code Used'].value_counts().reset_index()
plt.pie(promo_used['count'], labels= promo_used['Promo Code Used'], autopct= '%.0f%%')
plt.title('Promo Used Distribution')

discount_applied = shopping_data['Discount Applied'].value_counts().reset_index()
plt.pie(discount_applied['count'], labels= discount_applied['Discount Applied'], autopct= '%.0f%%')
plt.title('Discount Applied Distribution')

Leave a Reply

Your email address will not be published. Required fields are marked *

grandpashabet güncel giriş grandpashabet giriş grandpashabet grandpashabet güncel giriş grandpashabet giriş grandpashabet interbahis güncel giriş interbahis giriş interbahis interbahis pokerklas güncel giriş pokerklas giriş pokerklas pokerklas casibom güncel giriş casibom giriş casibom casibom güncel giriş casibom giriş casibom casibom güncel giriş casibom giriş casibom casibom güncel giriş casibom giriş casibom casibom güncel giriş casibom giriş casibom casibom güncel giriş casibom giriş casibom casibom güncel giriş casibom giriş casibom casibom güncel giriş casibom giriş casibom casibom güncel giriş casibom giriş casibom casibom güncel giriş casibom giriş casibom grandpashabet giriş grandpashabet grandpashabet güncel giriş grandpashabet giriş grandpashabet grandpashabet güncel giriş grandpashabet giriş grandpashabet grandpashabet giriş grandpashabet piabet güncel giriş piabet giriş piabet piabet mobilbahis güncel giriş mobilbahis giriş mobilbahis mobilbahis marsbahis twitter marsbahis güncel giriş marsbahis giriş marsbahis tarafbet güncel giriş tarafbet giriş tarafbet tarafbet meritking güncel giriş meritking giriş meritking meritking güncel giriş meritking giriş meritking piabellacasino güncel giriş piabellacasino giriş piabellacasino piabellacasino güncel giriş piabellacasino giriş piabellacasino galabet giriş galabet galabet güncel giriş galabet giriş galabet galabet güncel giriş galabet giriş galabet galabet giriş galabet galabet giriş galabet galabet güncel giriş galabet giriş galabet galabet güncel giriş galabet giriş galabet galabet giriş galabet galabet giriş galabet galabet güncel giriş galabet giriş galabet galabet güncel giriş galabet giriş galabet galabet giriş galabet casinoas güncel giriş casinoas giriş casinoas marsbahis güncel giriş marsbahis giriş marsbahis casibom casibom Online SMS Alma Geçici Telefon Numarası SMS Doğrulama Sanal Numara sms onay marsbahis güncel giriş marsbahis giriş marsbahis marsbahis güncel giriş marsbahis giriş marsbahis kingroyal güncel giriş kingroyal giriş kingroyal kralbet güncel giriş kralbet giriş kralbet perabet güncel giriş perabet giriş perabet perabet güncel giriş perabet giriş perabet matbet güncel giriş matbet giriş matbet matbet güncel giriş matbet giriş matbet pokerklas güncel giriş pokerklas giriş pokerklas pokerklas dedebet güncel giriş dedebet giriş dedebet maxwin güncel giriş maxwin giriş maxwin kalitebet güncel giriş kalitebet giriş kalitebet casinomilyon güncel giriş casinomilyon giriş casinomilyon pokerklas güncel giriş pokerklas giriş pokerklas pokerklas betjuve güncel giriş betjuve giriş betjuve casibom güncel giriş casibom giriş casibom herabet güncel giriş herabet giriş herabet herabet güncel giriş herabet giriş herabet herabet güncel giriş herabet giriş herabet matadorbet güncel giriş matadorbet giriş matadorbet matadorbet betturkey güncel giriş betturkey giriş betturkey pokerklas güncel giriş pokerklas giriş pokerklas pokerklas casibom güncel giriş casibom giriş casibom casibom güncel giriş casibom giriş casibom primebahis güncel giriş primebahis giriş primebahis queenbet güncel giriş queenbet giriş queenbet queenbet güncel giriş queenbet giriş queenbet betkanyon güncel giriş betkanyon giriş betkanyon pokerklas güncel giriş pokerklas giriş pokerklas pokerklas güncel giriş pokerklas giriş pokerklas pokerklas primebahis güncel giriş primebahis giriş primebahis primebahis güncel giriş primebahis giriş primebahis herabet güncel giriş herabet giriş herabet casibom güncel giriş casibom giriş casibom casibom güncel giriş casibom giriş casibom meritking güncel giriş meritking giriş meritking meritking güncel giriş meritking giriş meritking jojobet güncel giriş jojobet giriş jojobet jojobet güncel giriş jojobet giriş jojobet pokerklas güncel giriş pokerklas giriş pokerklas pokerklas casibom güncel giriş casibom giriş casibom casibom güncel giriş casibom giriş casibom casibom güncel giriş casibom giriş casibom betturkey güncel giriş betturkey giriş betturkey betturkey sahabet sahabet güncel giriş sahabet giriş sahabet betturkey güncel giriş betturkey giriş betturkey betturkey herabet güncel giriş herabet giriş herabet herabet güncel giriş herabet giriş herabet teslabahis güncel giriş teslabahis giriş teslabahis teslabahis güncel giriş teslabahis giriş teslabahis jojobet güncel giriş jojobet giriş jojobet betist güncel giriş betist giriş betist betist güncel giriş betist giriş betist betparibu güncel giriş betparibu giriş betparibu betparibu fixbet güncel giriş fixbet giriş fixbet fixbet betparibu güncel giriş betparibu giriş betparibu betparibu borsa takip borsa analiz borsa anlik borsa restbet güncel giriş restbet giriş restbet restbet casibom güncel giriş casibom giriş casibom betist güncel giriş betist giriş betist betist güncel giriş betist giriş betist pusulabet güncel giriş pusulabet giriş pusulabet pusulabet güncel giriş pusulabet giriş pusulabet betturkey güncel giriş betturkey giriş betturkey betturkey primebahis güncel giriş primebahis giriş primebahis casibom güncel giriş casibom giriş casibom tophillbet güncel giriş tophillbet giriş tophillbet tophillbet güncel giriş tophillbet giriş tophillbet casibom güncel giriş casibom giriş casibom primebahis güncel giriş primebahis giriş primebahis hititbet güncel giriş hititbet giriş hititbet primebahis güncel giriş primebahis giriş primebahis bahsegel güncel giriş bahsegel giriş bahsegel casibom güncel giriş casibom giriş casibom milanobet güncel giriş milanobet giriş milanobet milanobet primebahis güncel giriş primebahis giriş primebahis bahsegel güncel giriş bahsegel giriş bahsegel restbet güncel giriş restbet giriş restbet orisbet güncel giriş orisbet giriş orisbet orisbet casinoas güncel giriş casinoas giriş casinoas casinoas casibom güncel giriş casibom giriş casibom casibom güncel giriş casibom giriş casibom restbet güncel giriş restbet giriş restbet casibom güncel giriş casibom giriş casibom casibom güncel giriş casibom giriş casibom markajbet güncel giriş markajbet giriş