Mathew K Analytics

Lesson 10 · Market Research Analytics in Python

How to Load Survey and Market Data from CSV & Excel in Python | Market Research Analytics

We are learning how to load and explore real survey and market datasets using Python. Knowing how to correctly load data from CSV and Excel is critical for…

⬇ 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

Loading Survey and Market Data from CSV and Excel#

  • We are learning how to load and explore real survey and market datasets using Python.
  • Knowing how to correctly load data from CSV and Excel is critical for market research and customer analytics.
  • This lesson will show you practical techniques to read, clean, and understand survey and transactional customer data.
  • At the end, you will be able to import and preview real-world data for essential analysis.
import pandas as pd
import numpy as np
import openml
import warnings
warnings.filterwarnings('ignore')

Understanding Market Research Data Structures#

  • Survey datasets typically include columns for demographics (such as age, gender, location), customer responses (Likert scales, NPS, open text), and transaction details.
  • Market data may include campaign responses, purchase history, or customer feedback text.
  • Beginners often confuse codes (like NPS 0-10) or miss that text columns require different handling.
  • It is important to understand what each column means before analysis.
# Beginner Example 1: Load Customer Satisfaction Survey data
dataset = openml.datasets.get_dataset(42178)
df, _, _, _ = dataset.get_data(dataset_format='dataframe')
print(df.shape)
print(df.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: Load a marketing campaign dataset and fix columns
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']
print(df_campaign.shape)
print(df_campaign.head(3))
(45211, 17)
   age           job  marital  education default  balance housing loan  \
0   58    management  married   tertiary      no   2143.0     yes   no   
1   44    technician   single  secondary      no     29.0     yes   no   
2   33  entrepreneur  married  secondary      no      2.0     yes  yes   

   contact  day month  duration  campaign  pdays  previous poutcome response  
0  unknown    5   may     261.0         1   -1.0       0.0  unknown        1  
1  unknown    5   may     151.0         1   -1.0       0.0  unknown        1  
2  unknown    5   may      76.0         1   -1.0       0.0  unknown        1  
# Beginner Example 3: Load online retail Excel 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 4: Generate synthetic 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
# Beginner Example 5: Create a small open-ended customer feedback table
df_feedback = pd.DataFrame({
    'CustomerID':[1,2,3,4,5],
    'Feedback':[
        'Great service and friendly staff',
        'Delivery was slow and packaging was poor',
        'Excellent quality, will buy again',
        'Customer support needs improvement',
        'Good value for money'
    ]
})
print(df_feedback.shape)
print(df_feedback.head(3))
(5, 2)
   CustomerID                                  Feedback
0           1          Great service and friendly staff
1           2  Delivery was slow and packaging was poor
2           3         Excellent quality, will buy again
# Beginner Example 6: Simulate customer cohort signup activity over months
np.random.seed(0)
dates = pd.date_range('2021-01-01', periods=24, freq='ME')
df_cohort = pd.DataFrame({
    'CustomerID': np.random.randint(1000, 2000, len(dates)),
    'Signup_Month': dates,
    'Active_Users': np.random.randint(50, 300, len(dates))
})
print(df_cohort.shape)
print(df_cohort.head(3))
(24, 3)
   CustomerID Signup_Month  Active_Users
0        1684   2021-01-31           138
1        1559   2021-02-28           131
2        1629   2021-03-31           215

Going Deeper: Intermediate Data Insights#

  • Now that we know how to load survey and market datasets, we can explore structure, missing data, types, and response distribution.
  • Real data often needs cleaning and preprocessing before we use it for dashboards or modeling.
# Intermediate Example 1: Examine column types and summary in customer survey
print(df.dtypes)
print(df.describe(include='all').T.head(8))
gender               object
SeniorCitizen         uint8
Partner              object
Dependents           object
tenure                uint8
PhoneService         object
MultipleLines        object
InternetService      object
OnlineSecurity       object
OnlineBackup         object
DeviceProtection     object
TechSupport          object
StreamingTV          object
StreamingMovies      object
Contract             object
PaperlessBilling     object
PaymentMethod        object
MonthlyCharges      float64
TotalCharges         object
Churn                object
dtype: object
                  count unique          top  freq       mean        std  min  \
gender             7043      2         Male  3555        NaN        NaN  NaN   
SeniorCitizen    7043.0    NaN          NaN   NaN   0.162147   0.368612  0.0   
Partner            7043      2           No  3641        NaN        NaN  NaN   
Dependents         7043      2           No  4933        NaN        NaN  NaN   
tenure           7043.0    NaN          NaN   NaN  32.371149  24.559481  0.0   
PhoneService       7043      2          Yes  6361        NaN        NaN  NaN   
MultipleLines      7043      3           No  3390        NaN        NaN  NaN   
InternetService    7043      3  Fiber optic  3096        NaN        NaN  NaN   

                 25%   50%   75%   max  
gender           NaN   NaN   NaN   NaN  
SeniorCitizen    0.0   0.0   0.0   1.0  
Partner          NaN   NaN   NaN   NaN  
Dependents       NaN   NaN   NaN   NaN  
tenure           9.0  29.0  55.0  72.0  
PhoneService     NaN   NaN   NaN   NaN  
MultipleLines    NaN   NaN   NaN   NaN  
InternetService  NaN   NaN   NaN   NaN  
# Intermediate Example 2: Check for missing survey data
missing_perc = df.isna().mean().mul(100).sort_values(ascending=False)
print(missing_perc.head(10))
gender             0.0
SeniorCitizen      0.0
Partner            0.0
Dependents         0.0
tenure             0.0
PhoneService       0.0
MultipleLines      0.0
InternetService    0.0
OnlineSecurity     0.0
OnlineBackup       0.0
dtype: float64
# Intermediate Example 3: Value counts for a categorical field (InternetService usage)
print(df['InternetService'].value_counts(dropna=False))
InternetService
Fiber optic    3096
DSL            2421
No             1526
Name: count, dtype: int64
# Intermediate Example 4: Preview a campaign response rate
response_rate = df_campaign['response'].value_counts(normalize=True).mul(100)
print('Campaign response rate (%):')
print(response_rate)
Campaign response rate (%):
response
1    88.30152
2    11.69848
Name: proportion, dtype: float64
# Intermediate Example 5: Filter survey data for senior citizens with internet service
senior_net = df[(df['SeniorCitizen'] == 1) & (df['InternetService'] != 'No')]
print(senior_net[['gender', 'SeniorCitizen', 'InternetService', 'Churn']].head(5))
    gender  SeniorCitizen InternetService Churn
20    Male              1             DSL   Yes
30  Female              1     Fiber optic    No
31    Male              1     Fiber optic    No
34    Male              1             DSL    No
50  Female              1     Fiber optic    No
# Advanced Example 1: Pivot retail data by country to summarize sales
sales_by_country = df_retail.groupby('Country')['Price'].sum().sort_values(ascending=False)
print(sales_by_country.head(5))
Country
United Kingdom    2245715.474
EIRE                48447.190
France              43049.990
Germany             37666.000
Singapore           25108.890
Name: Price, dtype: float64
# Advanced Example 2: Calculate NPS (Net Promoter Score) from synthetic data
promoters = df_nps[df_nps['NPS_Score'] >= 9]
detractors = df_nps[df_nps['NPS_Score'] <= 6]
nps_score = (len(promoters) - len(detractors)) / len(df_nps) * 100
print(f'Net Promoter Score: {nps_score:.2f}')
Net Promoter Score: -47.60
# Advanced Example 3: Parse customer feedback for positive keyword frequency
positive_terms = ['great', 'excellent', 'good']
df_feedback['Feedback_Lower'] = df_feedback['Feedback'].str.lower()
for term in positive_terms:
    count = df_feedback['Feedback_Lower'].str.contains(term).sum()
    print(f"Feedbacks containing '{term}': {count}")
Feedbacks containing 'great': 1
Feedbacks containing 'excellent': 1
Feedbacks containing 'good': 1
# Advanced Example 4: Build a simple segmentation of customers by cohort month
cohort_group = df_cohort.groupby(df_cohort['Signup_Month'].dt.to_period('M'))['Active_Users'].sum()
print(cohort_group.head(6))
Signup_Month
2021-01    138
2021-02    131
2021-03    215
2021-04     75
2021-05    127
2021-06    122
Freq: M, Name: Active_Users, dtype: int32

Handling Errors in Market Research Data#

  • Real survey files often have missing responses or incorrectly coded values.
  • Let us demonstrate ways to deal with these common problems.
# Error Handling: Replace missing survey values with explicit label
df_missing = df.copy()
df_missing['PaymentMethod'] = df_missing['PaymentMethod'].fillna('Unknown')
print(df_missing['PaymentMethod'].value_counts())
PaymentMethod
Electronic check             2365
Mailed check                 1612
Bank transfer (automatic)    1544
Credit card (automatic)      1522
Name: count, dtype: int64
# Error Handling: Identify and fix likely aggregation mistakes
wrong_sum = df['Churn'].sum()  # Not meaningful for Yes/No text
print(f'Sum of Churn column (incorrect): {wrong_sum}')
churn_n = df['Churn'].value_counts()
print('Churn yes/no counts:')
print(churn_n)
Sum of Churn column (incorrect): NoNoYesNoYesYesNoNoYesNoNoNoNoYesNoNoNoNoYesNoYesNoYesNoNoNoYesYesNoYesNoNoNoNoNoNoYesNoYesYesNoNoNoNoNoNoNoYesNoNoNoYesNoYesNoYesNoNoNoNoNoNoNoNoYesNoNoNoNoNoNoNoNoNoNoNoNoNoNoNoYesNoYesNoNoNoNoNoNoNoNoNoNoNoNoYesNoYesNoYesNoNoNoNoYesNoNoNoNoNoYesNoNoYesNoNoNoYesNoNoNoNoYesNoNoNoYesNoNoNoNoYesNoYesYesNoNoNoNoYesNoYesNoNoNoNoNoYesNoNoNoYesNoNoNoNoNoNoNoNoNoYesNoNoNoNoYesNoYesNoNoYesNoYesNoNoYesYesNoNoYesNoYesNoYesYesNoNoNoNoNoYesNoNoNoNoNoNoNoNoNoNoNoNoNoNoNoYesYesNoYesNoNoNoNoNoNoNoNoNoYesNoNoYesNoNoNoYesNoNoNoNoYesNoNoYesNoNoYesNoNoNoNoNoNoNoNoYesYesNoNoYesYesNoNoNoNoNoYesNoYesYesNoNoNoNoNoNoYesNoYesNoYesNoYesYesYesNoNoNoNoNoNoNoYesNoNoYesYesYesYesNoNoNoNoNoNoNoNoYesNoYesNoNoNoNoYesNoNoNoNoNoNoNoYesNoNoYesYesNoYesNoNoNoNoNoNoYesNoNoNoNoNoYesYesYesYesNoNoYesNoNoNoNoNoNoYesNoNoNoNoNoNoYesYesYesNoNoYesNoNoNoNoNoNoYesNoNoNoNoNoYesNoNoNoNoNoYesNoNoNoYesNoYesNoYesYesNoNoNoNoNoNoNoNoNoNoYesNoNoNoNoYesNoNoNoNoNoYesYesYesNoNoNoNoNoNoNoYesYesNoNoNoNoNoNoNoNoNoNoYesNoNoYesNoNoNoNoNoNoNoNoNoNoNoYesYesNoNoNoNoNoNoYesNoNoNoNoNoNoNoNoYesYesNoNoNoNoNoYesNoYesNoNoYesYesNoNoYesYesNoYesNoNoYesNoNoNoNoYesNoNoYesNoNoYesNoNoYesYesNoNoNoNoNoYesNoYesYesNoNoNoYesNoNoYesNoNoYesNoNoNoNoYesYesNoNoNoNoNoNoNoNoNoYesNoNoNoNoNoNoNoNoYesYesNoYesNoNoNoNoNoNoNoYesNoNoNoNoNoNoNoNoNoNoNoNoNoYesNoNoNoNoYesNoNoNoNoNoNoYesYesYesNoNoYesNoNoNoNoNoNoNoNoNoYesNoNoNoNoNoNoNoNoNoNoNoNoNoYesYesYesNoNoNoNoNoNoNoNoNoNoNoNoYesNoNoNoNoYesYesNoNoNoNoYesNoNoYesYesNoYesYesNoNoYesYesNoYesNoYesYesNoNoYesNoNoNoYesNoYesNoNoNoNoNoYesNoYesNoNoNoYesNoYesNoNoYesNoNoYesNoNoNoNoNoNoYesNoNoNoNoNoYesNoNoNoYesNoNoNoNoNoNoNoYesNoNoNoNoYesNoNoNoNoNoNoNoNoNoNoNoYesYesYesNoNoNoYesNoYesNoNoNoNoNoNoNoNoNoNoNoYesNoNoNoNoNoNoNoNoNoNoNoNoYesNoNoYesNoNoYesYesNoNoNoNoNoNoNoNoYesYesYesYesNoNoYesNoYesNoNoNoYesNoYesNoNoNoNoNoNoNoNoNoNoNoNoNoYesNoYesNoNoYesNoNoNoYesYesYesYesNoNoNoNoYesNoYesNoNoNoNoNoNoYesYesNoYesNoYesNoNoNoYesNoNoYesNoNoYesNoYesNoYesNoNoNoNoNoNoNoNoNoNoYesNoYesNoNoNoNoYesYesYesYesNoNoYesNoNoNoNoYesNoNoYesNoNoNoYesNoYesNoNoNoNoNoNoYesNoYesNoYesNoNoNoNoYesNoNoYesYesNoNoYesNoNoNoNoYesNoNoNoNoYesNoNoNoNoNoNoNoNoNoNoYesYesNoNoNoNoNoYesNoNoNoYesNoNoNoNoNoNoNoYesNoNoYesNoYesNoNoNoNoYesNoNoNoNoNoNoNoNoYesYesYesNoNoYesYesNoNoYesNoYesYesNoYesNoNoNoNoYesNoYesNoNoNoNoNoNoNoNoNoYesYesYesNoNoYesYesNoNoNoNoYesYesYesNoNoNoNoNoYesYesNoNoNoNoNoNoNoNoNoNoYesNoYesYesNoNoYesNoNoNoNoNoNoYesYesNoNoYesNoNoNoNoNoYesYesNoNoYesYesNoYesYesYesYesNoNoNoNoNoYesNoNoYesNoYesYesNoYesNoNoNoYesNoNoNoNoNoYesNoYesYesNoYesNoNoNoNoNoNoNoNoYesNoNoNoNoYesNoNoNoNoNoNoNoNoYesNoYesNoNoNoNoNoNoNoNoYesNoNoYesYesNoNoNoNoYesYesNoNoNoNoNoNoNoNoNoNoNoYesNoNoNoYesYesNoNoNoNoNoNoNoNoNoYesNoYesNoYesNoNoNoNoNoNoNoYesNoYesNoNoYesNoYesNoNoYesNoNoNoYesNoNoNoNoNoNoYesNoNoNoNoNoNoNoNoNoYesNoNoYesNoNoYesNoYesYesNoNoYesYesNoNoYesNoNoNoNoYesYesYesNoNoNoNoNoNoYesNoNoNoYesNoYesNoNoNoNoYesYesNoNoNoYesYesNoYesNoYesNoYesNoNoNoYesNoNoNoYesNoNoNoNoYesNoNoNoNoNoNoNoNoNoNoNoNoNoNoNoNoYesNoNoNoNoNoYesNoNoYesNoNoNoNoYesNoNoNoNoYesNoYesNoYesYesYesNoNoYesYesNoNoNoNoYesNoNoNoNoYesYesNoYesNoNoNoNoNoNoYesYesNoNoYesYesNoYesNoNoNoNoYesNoYesNoNoNoNoNoYesNoNoNoNoYesYesYesYesNoNoYesYesNoNoNoNoYesNoNoNoNoYesNoNoNoNoNoNoYesYesNoNoNoNoYesNoNoNoNoNoYesYesNoNoNoNoYesYesNoNoYesNoNoNoNoYesNoYesNoNoNoNoNoNoNoNoYesNoYesNoNoNoNoYesNoNoNoNoNoYesNoYesNoNoYesNoNoNoNoNoNoNoYesNoNoNoNoNoNoNoNoYesNoYesNoYesNoNoYesNoNoNoNoNoYesNoNoYesYesNoNoNoYesYesNoNoNoNoNoNoYesYesNoNoNoNoNoYesNoYesNoNoNoYesNoNoNoNoNoNoYesNoNoNoYesNoNoNoYesNoNoNoNoNoYesNoNoYesNoNoNoNoNoNoNoYesNoNoYesNoNoNoNoYesNoNoNoNoYesNoNoNoYesNoYesNoNoNoNoNoYesYesNoYesNoNoYesNoNoYesNoNoNoNoNoNoNoYesNoNoYesNoYesYesYesNoNoNoNoNoNoNoNoNoNoNoNoYesNoNoYesNoNoNoNoYesNoYesYesNoNoNoYesNoNoNoNoYesNoNoNoNoNoYesNoNoYesNoNoYesYesNoNoNoNoNoYesYesNoNoNoNoNoNoYesNoNoNoNoYesYesNoYesNoNoYesYesNoNoNoYesNoNoYesNoNoNoYesYesYesNoNoNoNoNoYesNoNoYesNoYesNoNoNoNoNoNoNoNoNoNoYesNoNoNoNoNoNoNoYesNoYesNoNoNoNoYesYesNoYesNoNoNoYesNoNoNoNoNoNoNoNoNoNoNoNoYesNoNoNoNoNoNoNoNoYesYesNoNoYesNoYesNoNoYesNoNoYesNoNoNoNoYesNoNoNoYesNoNoNoNoNoNoNoNoNoNoNoNoNoNoNoNoNoNoYesYesYesNoNoNoNoNoNoNoYesNoNoYesYesNoYesNoNoNoYesNoNoNoNoYesNoNoNoYesNoNoNoNoNoNoNoYesYesYesNoNoNoNoNoNoNoNoNoNoNoYesYesYesNoNoNoNoNoNoNoNoYesNoYesNoYesYesNoNoYesNoNoNoNoNoNoNoNoYesNoYesYesYesYesNoYesNoYesYesNoYesNoNoNoNoNoYesNoNoNoNoNoNoNoNoNoNoNoYesYesNoNoYesNoNoNoYesNoNoYesYesNoNoNoNoNoYesYesNoNoNoNoNoYesNoNoNoNoNoNoNoNoNoNoNoYesNoNoYesNoNoNoNoNoNoYesYesYesNoNoNoNoNoYesNoNoNoNoNoNoNoNoNoYesNoNoNoYesNoYesNoNoYesYesNoNoNoNoNoNoNoNoNoNoYesNoYesNoNoYesNoNoNoYesNoYesNoNoNoNoYesNoNoYesYesNoYesYesNoYesNoNoYesNoYesNoNoYesYesNoNoNoYesYesYesYesYesYesNoYesNoYesNoNoNoYesNoYesYesNoNoNoYesNoNoNoNoNoYesNoNoYesYesNoNoNoNoYesYesNoNoNoNoNoNoNoNoYesNoNoNoNoYesYesNoNoYesNoNoNoYesNoNoNoNoNoNoNoYesYesNoNoNoYesNoNoYesNoNoNoNoNoYesYesYesYesYesNoNoNoNoNoNoNoYesYesNoNoNoNoYesNoNoYesYesNoNoNoNoNoNoNoNoNoNoYesNoNoNoNoNoNoNoYesNoNoYesNoYesYesNoNoYesNoNoNoNoNoNoYesNoNoNoNoNoNoNoNoNoNoNoNoNoNoYesYesNoNoNoNoYesNoYesNoNoNoYesYesNoNoNoNoNoNoYesNoNoNoNoNoNoNoNoYesYesNoNoNoNoNoYesNoNoYesNoNoNoNoNoNoNoYesNoYesNoYesYesYesNoNoNoNoNoYesNoNoNoNoNoNoNoNoYesYesNoNoNoNoNoNoYesNoNoNoNoNoNoNoNoNoNoNoNoYesNoYesNoNoNoNoNoNoNoNoNoNoNoNoNoYesNoYesYesNoYesNoNoNoYesYesNoNoNoYesYesNoYesNoNoNoYesYesYesNoYesNoYesNoNoYesYesNoNoYesYesNoYesNoNoYesNoNoYesNoNoNoNoNoNoNoNoNoNoNoNoNoNoNoNoNoNoNoYesYesNoNoNoNoNoNoNoNoNoNoNoYesYesNoYesNoNoNoNoNoNoNoNoNoNoNoNoNoNoNoNoNoNoNoNoNoYesNoNoNoNoYesYesNoNoNoNoNoNoNoNoNoNoYesYesNoNoNoNoNoNoNoNoNoNoNoNoNoYesNoNoNoYesNoNoNoNoNoNoNoYesYesYesNoNoNoNoYesNoNoYesNoNoNoNoNoNoNoNoYesNoNoYesYesNoNoYesNoNoNoNoNoNoYesNoNoNoYesNoYesNoYesNoYesNoNoYesYesNoNoYesNoNoNoNoNoNoNoNoYesYesNoNoYesNoNoYesNoNoNoNoNoNoNoNoYesNoNoYesNoYesNoNoYesNoNoNoYesNoYesNoNoNoNoNoNoNoNoNoYesNoNoNoNoNoYesNoNoNoYesNoYesYesNoNoNoYesNoNoNoNoYesYesYesYesNoNoNoNoNoNoYesNoNoNoNoNoNoYesNoNoNoNoNoNoNoNoNoNoNoNoNoNoNoNoYesNoNoYesYesNoNoYesNoNoYesNoNoYesYesNoNoYesYesNoNoNoNoNoNoNoNoNoNoYesNoNoNoNoNoNoNoNoNoNoNoNoNoNoNoNoNoYesYesYesYesYesNoYesYesNoYesYesNoYesNoNoNoNoNoNoNoNoNoYesNoYesNoNoYesNoNoNoYesYesNoNoYesYesYesNoNoNoNoNoNoYesNoNoYesYesNoNoNoNoNoNoYesNoNoNoNoNoYesYesNoNoNoYesNoNoNoYesNoYesNoNoYesYesNoNoYesNoYesNoYesNoNoNoNoNoNoNoNoNoNoNoNoYesNoNoYesYesYesNoNoYesNoNoNoNoNoNoNoNoYesYesNoNoNoNoNoYesNoYesNoNoNoNoNoNoNoNoNoNoYesYesNoNoNoYesNoNoYesNoNoNoYesYesNoNoYesNoNoNoNoYesNoNoNoNoNoNoNoYesYesNoNoNoNoYesYesNoNoYesYesNoNoNoYesNoNoNoNoNoYesNoNoNoNoYesNoYesYesNoNoNoYesNoYesNoNoNoNoNoNoNoYesNoNoYesNoNoYesNoNoYesYesNoNoNoNoNoNoYesNoYesNoNoNoNoNoYesNoNoNoNoNoNoYesNoNoNoNoNoNoNoNoNoNoNoNoNoNoNoNoYesYesNoNoNoNoNoNoYesNoYesNoYesNoYesNoYesNoYesNoNoNoNoNoNoNoYesYesNoYesYesNoYesYesNoNoNoNoNoYesNoNoNoYesNoNoYesYesNoNoYesNoNoNoNoNoNoNoNoNoYesYesNoYesNoNoNoNoNoNoNoNoNoNoNoNoNoNoYesYesNoNoNoNoNoNoNoYesNoNoNoNoYesYesYesNoNoNoNoYesNoYesNoNoYesNoNoNoNoYesNoNoYesYesNoNoNoNoNoNoNoNoNoNoNoNoNoNoNoYesNoNoNoNoNoNoYesNoNoYesNoNoYesYesNoYesYesNoNoNoNoNoNoNoNoYesNoNoYesNoNoNoNoNoNoYesNoYesYesYesYesNoNoYesNoNoNoNoNoYesNoYesYesYesNoNoYesNoYesYesNoNoNoNoYesNoNoYesNoNoYesNoNoNoNoNoYesNoNoNoNoNoNoNoNoYesNoYesYesNoYesNoNoNoYesNoYesNoNoYesNoYesNoNoNoNoNoYesNoNoNoYesYesNoNoNoNoNoNoNoYesNoNoNoYesNoNoNoYesNoYesNoNoNoNoNoYesNoNoNoNoNoNoNoYesYesNoYesYesNoYesYesNoNoYesYesNoNoNoNoNoNoNoNoNoNoYesYesNoNoNoNoNoNoNoNoNoNoNoNoNoYesNoNoYesNoNoYesNoNoNoNoYesNoYesNoNoYesNoNoNoNoNoYesNoNoYesNoNoYesNoNoNoNoNoNoNoNoYesNoNoNoNoNoNoYesNoNoNoNoNoNoNoYesNoNoNoNoYesNoNoNoNoNoNoNoNoNoNoYesYesNoNoNoYesYesNoYesNoNoYesNoNoNoNoNoNoNoNoYesNoYesNoNoYesNoNoNoNoNoYesYesYesNoNoYesNoNoNoNoNoNoNoNoNoYesYesNoNoNoNoNoNoYesNoNoNoNoNoNoYesYesYesNoNoNoNoNoNoYesNoNoNoNoNoNoNoYesYesNoNoYesNoNoYesYesNoNoNoYesNoYesNoYesNoNoNoYesNoYesNoNoNoYesNoNoNoNoYesYesYesYesNoNoNoYesYesNoNoYesNoYesNoYesNoNoNoNoNoNoYesNoYesYesNoNoNoNoNoYesNoNoYesYesYesNoNoNoNoNoNoNoNoNoNoNoNoNoNoNoNoYesNoNoNoNoNoYesNoYesYesNoNoNoYesNoNoNoNoNoNoNoYesYesNoYesNoYesNoNoYesNoNoNoNoNoNoYesYesNoNoNoNoNoNoNoNoYesNoNoNoNoNoNoYesNoNoYesNoNoNoYesNoNoNoNoYesNoNoNoNoNoYesNoNoNoNoNoYesNoNoNoNoNoYesNoNoNoNoYesNoNoNoYesYesNoNoYesYesNoNoNoNoNoNoNoNoNoNoNoNoNoNoNoNoYesYesNoNoNoNoNoNoYesYesYesYesYesNoNoNoYesNoYesNoNoNoNoYesNoNoNoNoYesNoNoNoNoNoYesYesNoNoNoYesNoNoNoNoNoYesYesNoNoYesNoYesNoNoNoNoNoNoNoNoNoYesNoNoYesNoNoNoNoNoYesYesNoNoNoYesYesYesNoYesYesNoNoNoYesNoNoYesNoNoNoNoYesNoYesNoNoNoNoYesNoYesNoNoNoYesNoNoNoNoNoNoNoNoYesYesNoNoNoNoNoYesYesNoYesNoNoNoNoNoNoNoNoNoNoNoYesNoNoNoNoNoNoNoNoNoYesNoNoNoYesNoNoNoNoYesYesYesYesNoNoNoNoYesYesYesYesNoNoNoYesYesNoYesYesNoNoNoYesNoYesNoNoNoYesNoYesNoNoNoNoNoNoNoNoNoNoYesNoNoYesNoNoNoNoYesNoNoNoYesYesYesNoNoYesNoNoNoNoNoNoYesNoNoNoNoNoYesNoYesYesNoNoYesNoNoNoNoNoYesYesNoNoYesNoNoNoYesNoNoYesNoNoNoNoYesYesYesNoYesNoNoNoYesNoNoNoNoYesYesNoNoYesNoYesNoYesNoNoNoYesNoNoYesNoYesNoYesNoYesNoYesNoNoNoNoNoNoNoYesNoNoNoNoNoYesNoNoNoNoNoNoNoYesYesYesNoNoYesNoNoYesNoNoNoYesNoYesYesYesNoNoNoYesNoNoNoNoNoNoNoNoNoNoNoNoNoNoYesNoNoNoYesNoNoYesNoNoNoYesNoYesNoYesNoNoNoNoNoNoNoYesYesNoYesNoNoNoNoNoNoNoNoNoNoNoNoNoNoYesYesNoNoNoYesYesNoNoNoNoNoYesYesYesNoNoNoYesYesNoNoYesNoNoNoNoYesNoNoNoNoNoNoYesNoNoYesNoNoYesYesNoNoNoYesNoNoYesNoNoYesNoYesNoNoNoYesNoNoNoNoNoNoNoNoYesNoNoNoYesYesNoNoNoYesNoNoYesNoNoNoYesNoNoNoYesNoNoYesYesNoNoNoYesNoNoNoNoNoYesNoNoNoNoNoNoYesNoNoNoNoNoNoYesNoYesNoNoNoYesNoYesNoNoNoNoNoNoNoNoNoNoNoNoNoNoNoNoNoYesNoNoNoNoNoNoYesNoNoNoYesNoYesYesNoNoYesYesNoYesNoNoNoNoNoNoNoYesYesNoNoNoYesNoNoYesYesYesYesNoNoNoYesYesNoNoNoNoNoNoNoNoYesNoNoNoNoNoNoNoYesNoNoYesNoNoNoNoNoNoNoNoNoNoNoYesNoNoNoNoNoNoYesNoNoYesYesNoNoNoNoNoYesNoYesNoNoYesNoNoYesNoNoYesNoNoNoNoYesNoNoNoNoNoNoNoNoNoNoNoNoNoNoYesNoYesNoNoYesNoNoNoNoNoYesNoYesNoYesNoNoNoYesNoYesNoNoNoNoNoNoNoNoYesNoNoNoNoNoNoNoNoNoNoNoYesYesYesYesNoNoNoNoNoNoNoNoNoNoNoYesNoYesNoYesNoYesNoNoNoNoYesNoNoYesYesNoNoNoNoNoNoNoNoNoNoNoNoYesYesNoNoYesYesNoNoYesNoNoYesYesNoNoYesNoNoYesYesNoNoYesNoNoNoNoNoNoNoNoNoNoYesYesNoYesNoYesYesNoNoYesNoNoNoNoNoNoNoNoNoNoYesNoNoNoYesNoNoYesYesNoNoNoNoNoNoNoYesNoNoYesNoNoYesYesNoNoNoNoNoNoNoNoNoNoYesNoYesNoNoNoNoYesYesNoNoNoYesNoNoNoNoNoNoNoNoNoNoNoNoNoNoYesYesNoNoNoNoNoNoNoNoNoNoNoYesNoNoYesNoYesNoNoNoNoNoNoYesNoYesYesNoNoNoNoNoYesNoNoYesNoNoNoNoNoNoNoYesNoNoNoYesYesNoNoNoNoNoYesNoNoNoYesNoNoNoNoNoNoNoNoNoNoNoNoNoYesNoYesNoYesNoYesNoYesNoNoYesNoYesNoNoYesYesNoNoYesYesYesNoYesNoYesNoNoYesNoNoNoNoYesNoNoNoYesNoYesNoNoNoNoNoYesNoNoNoNoNoNoYesNoNoNoYesNoNoYesYesNoNoNoNoNoYesNoNoNoYesNoNoNoYesYesNoYesNoNoNoYesNoNoYesNoNoNoYesYesNoNoYesYesNoYesYesNoYesNoNoYesNoYesNoYesNoNoNoNoNoNoNoYesNoYesNoNoNoNoYesYesNoNoNoNoYesNoNoNoNoNoNoNoNoNoNoNoNoNoNoNoYesNoNoNoNoNoNoNoNoYesNoNoYesNoNoNoNoNoNoNoNoNoNoNoNoYesNoNoYesNoNoNoNoNoYesNoNoNoNoYesNoNoNoNoNoNoYesYesNoNoNoNoNoYesNoYesNoYesNoNoYesNoNoNoNoNoYesNoYesNoNoNoNoNoNoYesNoNoYesYesNoNoNoNoNoNoYesNoYesNoYesNoYesYesNoNoYesYesNoYesNoNoYesNoNoNoYesNoNoNoNoNoNoYesNoNoNoNoYesNoNoYesNoNoNoNoNoNoNoNoNoNoNoNoYesNoYesNoYesNoYesNoNoNoNoNoNoNoNoYesNoNoNoYesNoYesNoNoNoNoNoYesNoNoYesNoYesNoYesNoNoNoYesNoYesNoNoNoNoYesNoNoNoNoNoNoYesNoYesNoYesNoNoNoNoNoNoNoNoNoYesNoNoNoYesNoNoYesNoNoYesNoNoNoNoYesNoNoNoNoNoNoNoNoNoYesYesYesNoYesYesNoNoNoYesNoNoNoYesNoNoYesYesNoNoNoNoNoNoNoNoNoYesNoYesNoNoYesNoNoNoNoYesYesNoNoYesNoNoNoNoYesNoNoNoNoNoYesNoNoNoNoNoYesNoNoNoNoNoYesYesYesNoNoNoNoNoNoYesNoNoNoNoNoNoNoNoNoYesNoNoNoNoYesYesYesYesNoYesNoNoNoNoYesNoYesNoYesNoNoNoNoNoNoNoNoNoNoNoYesNoNoNoYesNoNoNoNoNoNoNoNoNoYesNoNoYesYesNoNoNoYesYesNoYesYesNoNoNoYesYesYesNoNoYesYesNoNoNoYesYesNoYesNoNoNoNoNoNoYesNoNoNoYesNoNoYesYesYesNoNoNoNoNoNoNoYesNoNoYesYesNoYesNoNoNoYesNoYesNoYesYesNoNoNoNoNoNoNoNoNoYesNoNoNoNoNoNoYesNoNoNoYesNoNoYesNoNoNoNoNoYesYesNoYesNoNoNoYesNoNoNoNoNoYesYesNoNoNoNoNoNoNoNoYesNoNoYesYesYesNoNoNoNoYesYesNoNoNoNoNoYesNoNoNoNoNoNoNoNoNoYesNoNoNoYesYesNoNoNoNoNoNoYesYesYesNoNoNoNoYesNoNoNoNoNoYesYesNoNoNoYesNoNoNoYesNoNoYesNoYesNoYesNoNoYesYesNoYesYesNoNoNoNoNoNoNoNoNoNoNoNoNoNoNoNoNoNoNoYesNoNoNoNoNoNoNoNoNoNoYesNoNoYesNoNoNoNoNoYesNoNoYesNoYesNoNoNoYesNoNoYesNoNoNoNoNoNoNoYesNoNoNoYesNoNoNoNoNoNoNoNoYesNoNoYesYesNoNoYesYesYesNoNoNoNoNoNoNoNoNoNoNoNoYesNoYesNoYesNoNoNoNoNoNoNoNoYesNoNoNoYesYesNoNoNoYesNoNoNoNoYesYesYesNoNoNoNoNoNoNoNoNoNoNoYesNoYesNoNoYesNoYesNoNoNoNoYesNoYesNoYesNoYesNoNoNoNoNoNoNoNoNoNoYesYesYesNoNoNoNoYesNoNoNoNoYesYesNoNoYesNoYesNoNoNoNoNoNoNoNoYesNoNoYesYesNoNoYesYesNoNoNoNoNoNoYesYesNoNoYesNoNoNoNoNoYesNoNoNoNoNoNoNoYesYesNoNoNoYesNoNoNoYesNoNoYesNoNoYesYesNoNoNoNoYesYesNoYesNoYesNoNoYesNoYesNoNoYesNoYesNoYesNoNoNoNoNoNoNoNoNoNoNoYesNoYesNoNoYesNoNoNoNoNoNoNoNoYesNoNoNoNoYesNoYesNoYesNoNoNoNoYesYesYesNoYesNoNoNoNoYesNoNoNoYesNoNoNoYesNoYesNoYesNoNoNoNoYesNoNoNoNoYesNoNoNoNoNoNoYesYesNoNoNoNoYesYesYesNoNoNoNoNoNoNoNoNoYesYesYesNoYesYesYesNoNoYesNoYesNoNoNoNoYesNoNoNoNoNoNoYesNoYesNoNoNoYesNoNoNoNoNoNoNoNoNoNoNoNoNoYesNoYesNoYesYesNoNoYesNoNoYesNoYesNoNoNoYesNoNoYesNoNoNoNoNoNoNoNoYesNoNoNoYesNoNoNoYesNoNoYesNoNoYesNoYesNoYesYesYesNoNoYesYesNoYesNoNoNoNoNoYesNoYesYesNoNoYesNoNoNoYesNoYesYesNoNoNoNoYesNoNoNoNoNoYesYesNoNoNoNoNoYesYesYesNoNoNoYesNoYesNoYesNoYesNoNoYesYesNoYesNoNoNoNoYesNoYesNoNoNoNoNoNoNoNoYesNoYesNoNoNoNoNoYesNoNoNoNoNoNoNoYesYesYesNoNoYesYesNoYesNoNoNoNoNoNoNoNoNoYesYesYesNoNoNoYesNoNoNoYesNoNoNoNoYesNoNoYesYesNoNoYesNoNoNoYesNoYesNoNoNoYesNoNoNoNoNoNoNoNoNoYesNoNoYesNoNoNoNoYesNoNoNoYesNoNoNoNoNoNoNoNoYesNoNoNoNoNoYesNoNoNoNoNoNoNoNoNoNoNoNoNoYesNoNoYesYesNoNoNoYesNoNoNoNoYesNoNoNoNoNoYesYesNoNoNoYesNoNoYesNoNoNoYesNoYesNoNoYesNoYesNoNoNoNoNoNoNoYesYesNoNoNoNoYesYesNoNoNoNoNoNoNoNoYesNoNoNoYesNoNoNoNoYesNoYesNoNoNoNoYesNoNoYesNoNoYesNoNoNoNoNoNoYesYesYesNoYesNoYesYesNoNoYesNoNoNoYesNoNoNoYesNoNoYesNoNoYesNoNoNoNoNoYesYesNoNoNoNoYesNoYesNoNoNoYesNoNoNoNoNoNoNoNoNoNoNoNoNoNoNoNoNoNoYesYesYesYesNoNoYesNoNoNoNoYesYesYesNoYesYesNoNoNoNoNoNoNoNoYesYesNoNoNoNoNoNoNoNoYesYesYesNoNoNoYesNoNoYesNoNoNoNoNoNoNoNoYesNoNoNoNoYesNoYesYesNoYesNoNoNoNoNoNoNoYesNoNoNoNoNoNoYesNoNoYesNoNoNoYesNoNoNoNoNoNoNoYesNoNoNoYesNoYesNoYesYesNoYesNoNoYesYesYesNoNoYesNoNoNoNoYesNoNoNoNoNoYesNoNoNoNoNoNoNoNoNoYesNoYesNoYesNoNoNoNoNoYesNoNoNoNoNoYesNoYesNoNoYesNoNoYesYesNoYesNoNoNoNoNoNoNoNoYesNoNoNoNoYesYesNoNoNoNoNoNoNoNoNoNoNoNoNoNoNoNoNoNoYesYesNoNoNoNoYesNoNoNoNoNoYesNoNoNoYesYesNoNoNoYesNoNoNoNoYesYesNoNoYesNoYesNoNoNoNoNoNoNoNoYesNoYesYesNoNoYesNoYesNoYesYesNoYesNoNoNoNoNoNoYesNoNoNoYesNoNoNoNoYesNoYesNoYesNoNoYesNoNoYesNoYesNoNoNoYesNoNoNoYesNoNoNoYesNoNoNoYesNoNoNoYesNoNoNoYesYesNoNoYesNoYesNoNoYesYesNoNoNoNoNoNoNoNoNoNoNoNoNoNoYesYesNoNoNoNoNoNoNoNoYesYesNoNoNoNoNoYesNoNoNoYesNoNoNoNoNoYesNoNoNoYesNoYesYesNoNoNoYesNoNoNoNoNoNoNoYesNoYesYesNoNoNoNoNoNoYesYesNoNoNoYesNoNoNoYesYesNoNoYesNoNoNoNoNoNoNoYesNoNoNoNoNoYesNoYesNoNoYesNoYesNoNoNoNoYesNoNoNoNoNoYesNoNoYesNoNoNoNoYesNoNoYesNoYesNoNoNoNoYesNoYesYesYesNoNoNoNoNoYesNoNoYesNoNoNoNoNoNoYesNoNoYesNoNoYesNoNoNoNoNoNoYesNoNoNoNoYesNoNoNoYesNoNoNoNoNoNoYesNoNoNoYesNoNoNoNoNoYesNoNoNoYesNoNoNoNoNoYesNoNoNoYesNoNoNoNoYesNoNoNoNoNoNoYesNoYesNoNoNoNoNoNoNoNoNoNoYesNoNoNoNoNoYesNoNoYesNoNoNoYesNoYesYesNoYesNoNoNoYesYesNoYesNoNoNoNoNoYesNoYesYesYesYesNoNoNoNoNoYesYesNoYesNoYesNoNoNoYesNoYesYesNoYesNoNoNoNoNoYesNoYesYesNoNoNoYesNoYesYesNoNoNoYesYesNoYesNoYesNoNoNoYesNoNoNoYesYesNoNoNoNoNoNoNoNoNoNoNoNoNoNoNoNoNoNoNoNoNoNoNoNoNoNoYesYesNoYesNoNoNoYesNoYesYesNoNoNoNoYesYesYesYesYesNoNoYesNoNoNoYesNoNoNoYesNoYesYesNoYesYesNoNoNoNoNoYesYesYesNoNoNoNoNoNoYesNoNoNoNoNoNoNoNoNoNoNoNoYesNoNoNoYesNoYesNoNoNoNoNoNoYesNoNoNoNoNoNoNoNoNoNoNoNoYesYesNoNoNoNoNoYesNoNoNoNoNoNoNoNoNoNoNoNoNoNoNoYesNoNoNoNoYesNoNoNoNoNoNoNoYesYesYesNoNoNoNoNoYesNoYesNoNoNoNoNoNoNoYesNoNoNoNoNoYesYesNoNoNoYesYesNoYesNoNoNoNoNoNoNoNoYesNoNoYesNoYesNoYesNoNoNoNoNoNoNoYesYesNoNoNoNoNoNoNoYesNoNoNoYesYesNoNoYesNoYesYesNoNoNoYesNoNoNoYesNoNoNoNoNoNoNoNoYesYesYesNoYesNoNoYesNoNoYesNoYesYesNoYesNoNoNoNoNoNoYesNoNoNoNoYesNoYesYesNoNoNoYesNoNoYesNoNoNoNoNoNoYesNoNoNoNoYesNoYesYesYesNoYesNoYesNoYesYesNoNoNoNoNoNoNoYesYesNoNoNoNoNoYesYesYesNoNoNoNoNoNoYesYesNoYesNoNoYesNoNoNoNoNoNoNoYesYesNoNoNoNoNoYesNoNoNoYesNoNoNoNoNoYesNoYesNoNoNoYesNoNoYesNoNoYesNoNoNoNoNoNoYesNoYesNoNoNoNoNoNoYesYesNoNoNoNoNoNoNoYesYesNoNoNoNoYesYesYesYesYesYesNoNoNoNoNoNoNoYesNoNoNoNoNoYesNoNoNoNoYesNoYesNoNoYesNoNoYesNoYesNoNoNoNoYesNoYesYesYesYesNoNoNoNoNoNoYesNoNoYesNoNoNoNoYesNoNoNoNoNoYesNoYesNoNoNoNoNoNoYesNo
Churn yes/no counts:
Churn
No     5174
Yes    1869
Name: count, dtype: int64
# Error Handling: Convert Likert/NPS scale numerics to text categories
df_nps['NPS_Category'] = np.where(df_nps['NPS_Score'] >= 9, 'Promoter',
    np.where(df_nps['NPS_Score'] <= 6, 'Detractor', 'Passive'))
print(df_nps[['NPS_Score', 'NPS_Category']].head(5))
   NPS_Score NPS_Category
0          2    Detractor
1          0    Detractor
2          4    Detractor
3          3    Detractor
4          9     Promoter

Best Practices: Patterns for Market Research Analytics#

  • Grouping and segmenting customers or responses multiplies insight.
  • Cross-tabulating demographics and satisfaction can find key drivers.
  • Building indices or trend lines makes reports easier to interpret.
# Best Practice: Segment NPS by region
nps_by_region = df_nps.groupby('Region')['NPS_Score'].mean()
print(nps_by_region)
Region
East     4.504425
North    5.214765
South    4.719008
West     5.025641
Name: NPS_Score, dtype: float64
# Best Practice: Cross-tabulate Churn by payment method
churn_by_payment = pd.crosstab(df['PaymentMethod'], df['Churn'])
print(churn_by_payment.head(6))
Churn                        No   Yes
PaymentMethod                        
Bank transfer (automatic)  1286   258
Credit card (automatic)    1290   232
Electronic check           1294  1071
Mailed check               1304   308
# Best Practice: Aggregate customer retention trend over time
df_cohort['YearMonth'] = df_cohort['Signup_Month'].dt.to_period('M')
trend = df_cohort.groupby('YearMonth')['Active_Users'].sum()
print(trend.tail(6))
YearMonth
2022-07    227
2022-08    293
2022-09     79
2022-10    197
2022-11    197
2022-12    192
Freq: M, Name: Active_Users, dtype: int32

End-to-End: Rapid Market Research Use Case#

  • Let us do a quick end-to-end problem: load a survey, clean it, summarize key metrics, and recommend an action based on data.
# 1. Load and preview survey data
dataset = openml.datasets.get_dataset(42178)
df, _, _, _ = dataset.get_data(dataset_format='dataframe')
print(df.head(2))
   gender  SeniorCitizen Partner Dependents  tenure PhoneService  \
0  Female              0     Yes         No       1           No   
1    Male              0      No         No      34          Yes   

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

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

  PaperlessBilling     PaymentMethod  MonthlyCharges TotalCharges Churn  
0              Yes  Electronic check           29.85        29.85    No  
1               No      Mailed check           56.95       1889.5    No  
# 2. Clean missing data in PaymentMethod
df['PaymentMethod'] = df['PaymentMethod'].fillna('Unknown')
# 3. Group and calculate churn rates by payment type
churn_rates = df.groupby('PaymentMethod')['Churn'].value_counts(normalize=True).unstack().fillna(0)
print(churn_rates)
Churn                            No       Yes
PaymentMethod                                
Bank transfer (automatic)  0.832902  0.167098
Credit card (automatic)    0.847569  0.152431
Electronic check           0.547146  0.452854
Mailed check               0.808933  0.191067
# 4. Recommend a business action based on the result
highest_churn = churn_rates['Yes'].idxmax()
print(f'Recommend targeting {highest_churn} customers with loyalty offers.')
Recommend targeting Electronic check customers with loyalty offers.
 

Found this useful?

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