Mathew K Analytics

Lesson 51 · Market Research Analytics in Python

Turning Market Analysis into Business Insights with Python

In this lesson, we explore how real customer and market data is used to answer business questions. We focus on transforming market analysis into actionable…

⬇ Download notebookOpen in Colab ↗

What you'll learn

Data

No separate download needed — the notebook creates or downloads everything it uses.

📓 Full notebook

Download .ipynb

Turning Market Analysis into Business Insights#

  • In this lesson, we explore how real customer and market data is used to answer business questions.
  • We focus on transforming market analysis into actionable insights.
  • Understanding customer satisfaction, campaign response, and purchase behavior helps improve products, services, or marketing.
  • You will learn how to extract key findings from datasets and deliver clear recommendations.
  • Practice converting data patterns into business actions.
import pandas as pd
import numpy as np
import openml
import warnings
warnings.filterwarnings('ignore')

Understanding Customer and Market Datasets#

  • We will use authentic customer satisfaction surveys, marketing campaign responses, and online retail data.
  • Each dataset captures real-world details, from demographics to open-ended customer feedback.
  • Survey data often comes with ranges, ratings, or missing responses.
  • Beginners often forget to check for missing values, encoding mistakes, or biased group comparisons.
# Beginner Example 1: Loading Customer Satisfaction Data
dataset = openml.datasets.get_dataset(42178)
df_satisfaction, _, _, _ = dataset.get_data(dataset_format='dataframe')
print(df_satisfaction.shape)
print(df_satisfaction.head(3))
(7043, 20)
   gender  SeniorCitizen Partner Dependents  tenure PhoneService  \
0  Female              0     Yes         No       1           No   
1    Male              0      No         No      34          Yes   
2    Male              0      No         No       2          Yes   

      MultipleLines InternetService OnlineSecurity OnlineBackup  \
0  No phone service             DSL             No          Yes   
1                No             DSL            Yes           No   
2                No             DSL            Yes          Yes   

  DeviceProtection TechSupport StreamingTV StreamingMovies        Contract  \
0               No          No          No              No  Month-to-month   
1              Yes          No          No              No        One year   
2               No          No          No              No  Month-to-month   

  PaperlessBilling     PaymentMethod  MonthlyCharges TotalCharges Churn  
0              Yes  Electronic check           29.85        29.85    No  
1               No      Mailed check           56.95       1889.5    No  
2              Yes      Mailed check           53.85       108.15   Yes  
# Beginner Example 2: Loading Online Retail Transaction Data
url = 'https://archive.ics.uci.edu/ml/machine-learning-databases/00502/online_retail_II.xlsx'
df_retail = pd.read_excel(url, sheet_name='Year 2010-2011')
df_retail['InvoiceDate'] = pd.to_datetime(df_retail['InvoiceDate'])
print(df_retail.shape)
print(df_retail.head(3))
(541910, 8)
  Invoice StockCode                         Description  Quantity  \
0  536365    85123A  WHITE HANGING HEART T-LIGHT HOLDER         6   
1  536365     71053                 WHITE METAL LANTERN         6   
2  536365    84406B      CREAM CUPID HEARTS COAT HANGER         8   

          InvoiceDate  Price  Customer ID         Country  
0 2010-12-01 08:26:00   2.55      17850.0  United Kingdom  
1 2010-12-01 08:26:00   3.39      17850.0  United Kingdom  
2 2010-12-01 08:26:00   2.75      17850.0  United Kingdom  
# Beginner Example 3: Creating and Loading NPS Survey Data
np.random.seed(42)
df_nps = pd.DataFrame({
    'CustomerID': range(1,501),
    'Age': np.random.randint(18,70,500),
    'Region': np.random.choice(['North','South','East','West'],500),
    'NPS_Score': np.random.randint(0,11,500)
})
print(df_nps.shape)
print(df_nps.head(3))
(500, 4)
   CustomerID  Age Region  NPS_Score
0           1   56   West          2
1           2   69  North          0
2           3   46   East          4
# Intermediate Example 1: Summarizing Customer Satisfaction by Senior Status
satisfaction_by_senior = df_satisfaction.groupby('SeniorCitizen')['Churn'].value_counts(normalize=True).unstack()
print(satisfaction_by_senior)
Churn                No       Yes
SeniorCitizen                    
0              0.763938  0.236062
1              0.583187  0.416813
# Intermediate Example 2: Calculating Repeat Purchase Rate in Retail Data
repeat_customers = df_retail.groupby('Customer ID').size().reset_index(name='Transactions')
repeat_rate = (repeat_customers['Transactions'] > 1).mean()
print(f"Repeat purchase rate: {repeat_rate:.2%}")
Repeat purchase rate: 98.19%
# Intermediate Example 3: Summarizing Marketing Campaign Response by Education Level
dataset = openml.datasets.get_dataset(1461)
df_campaign, _, _, _ = dataset.get_data(dataset_format='dataframe')
df_campaign.columns = ['age','job','marital','education','default','balance','housing','loan','contact','day','month',
                      'duration','campaign','pdays','previous','poutcome','response']
response_by_education = df_campaign.groupby('education')['response'].value_counts(normalize=True).unstack()
print(response_by_education)
response          1         2
education                    
primary    0.913735  0.086265
secondary  0.894406  0.105594
tertiary   0.849936  0.150064
unknown    0.864297  0.135703
# Intermediate Example 4: Average NPS Score by Region
avg_nps_region = df_nps.groupby('Region')['NPS_Score'].mean()
print(avg_nps_region)
Region
East     4.504425
North    5.214765
South    4.719008
West     5.025641
Name: NPS_Score, dtype: float64
# Intermediate Example 5: Analyzing Transaction Value Over Time
df_retail['TotalValue'] = df_retail['Quantity'] * df_retail['Price']
monthly_sales = df_retail.set_index('InvoiceDate').resample('M')['TotalValue'].sum()
print(monthly_sales.tail(6))
InvoiceDate
2011-07-31     681300.111
2011-08-31     682680.510
2011-09-30    1019687.622
2011-10-31    1070704.670
2011-11-30    1461756.250
2011-12-31     433686.010
Freq: ME, Name: TotalValue, dtype: float64
# Advanced Example 1: Identifying At-Risk Customers via Satisfaction and Churn
risk_group = df_satisfaction[(df_satisfaction['Churn']=='Yes') & (df_satisfaction['tenure'] <= 12)]
at_risk_pct = len(risk_group) / len(df_satisfaction)
print(f"Percent of new customers at risk of churn: {at_risk_pct:.2%}")
Percent of new customers at risk of churn: 14.72%
# Advanced Example 2: Calculating Customer Lifetime Value (CLV) for Top Customers
clv = df_retail.groupby('Customer ID')['TotalValue'].sum().sort_values(ascending=False)
top_clv = clv.head(5)
print(top_clv)
Customer ID
14646.0    279489.02
18102.0    256438.49
17450.0    187482.17
14911.0    132572.62
12415.0    123725.45
Name: TotalValue, dtype: float64
# Advanced Example 3: Trend Analysis of NPS Over Time by Region
df_nps['Month'] = np.random.choice(pd.date_range('2022-01-01', periods=12, freq='M'), size=len(df_nps))
nps_trend = df_nps.groupby(['Region','Month'])['NPS_Score'].mean().unstack('Region')
print(nps_trend.tail(6))
Region          East     North     South      West
Month                                             
2022-07-31  5.333333  5.909091  4.666667  7.250000
2022-08-31  3.166667  4.555556  4.615385  4.500000
2022-09-30  3.272727  5.266667  5.090909  5.600000
2022-10-31  3.266667  4.500000  3.444444  5.181818
2022-11-30  4.555556  6.052632  4.333333  4.357143
2022-12-31  4.714286  4.300000  5.100000  4.750000
# Error Handling Example: Checking for Missing Survey Responses
missing_counts = df_satisfaction.isnull().sum()
print(missing_counts[missing_counts > 0])
Series([], dtype: int64)
# Error Example: Incorrect Aggregation when Grouping by Categorical Columns
try:
    wrong_group = df_nps.groupby('NPS_Score').Region.mean()
except Exception as e:
    print('Error:', e)
Error: agg function failed [how->mean,dtype->object]
# Error Example: Misinterpreting NPS ScalesCounting 'Promoters' Correctly
promoters = df_nps['NPS_Score'] >= 9
print(f"Percent promoters: {promoters.mean():.2%}")
Percent promoters: 17.00%

Best Practices for Market Research Analytics#

  • Segment results by customer type, location, and tenure to find patterns.
  • Use cross-tabulation to see how two variables interact (e.g., churn by contract type).
  • Construct indexes or summary scores for easier business decisions.
  • Visualize time trends to catch seasonal effects or sudden changes.
# Pattern Example: Cross-Tabulation of Customer Churn by Contract Type
churn_by_contract = pd.crosstab(df_satisfaction['Contract'], df_satisfaction['Churn'], normalize='index')
print(churn_by_contract)
Churn                 No       Yes
Contract                          
Month-to-month  0.572903  0.427097
One year        0.887305  0.112695
Two year        0.971681  0.028319
# Pattern Example: Trend AnalysisMonthly New Customers in Online Retail
df_retail['SignupMonth'] = df_retail['InvoiceDate'].dt.to_period('M')
monthly_new = df_retail.groupby('SignupMonth')['Customer ID'].nunique()
print(monthly_new.tail(6))
SignupMonth
2011-07     993
2011-08     980
2011-09    1302
2011-10    1425
2011-11    1711
2011-12     686
Freq: M, Name: Customer ID, dtype: int64

Tiny End-to-End Problem: From Survey to Strategic Recommendation#

  • Suppose NPS dropped in the West region for two consecutive months.
  • What action should management take?
  • Analyze the NPS trend, identify the segment, and prepare a short recommendation.
# Solution: Analyze NPS Drop for West Region
nps_trend_west = nps_trend['West']
nps_trend_west_recent = nps_trend_west.tail(3)
print("Recent West Region NPS:")
print(nps_trend_west_recent)
Recent West Region NPS:
Month
2022-10-31    5.181818
2022-11-30    4.357143
2022-12-31    4.750000
Name: West, dtype: float64
 

Found this useful?

All lessons, notebooks and datasets here are free. If they helped you, a coffee keeps new lessons coming.