Free GuideIntermediate
50 min read
#EDA#Univariate Analysis#Bivariate Analysis#Multivariate#Hypothesis Generation

07. Exploratory Data Analysis (EDA) Techniques

Structured EDA methodology: univariate distribution analysis, bivariate relationships, multivariate interaction discovery, segment comparisons, and data-driven hypothesis generation.

Notebook 7: Exploratory Data Analysis (EDA) Techniques

Module: Data Analytics Level: Intermediate Prerequisites: Notebook 6 (Descriptive Statistics and Probability Foundations) Estimated Time: 4 hours


Table of Contents#

  1. What EDA Is and Why It Comes Before Conclusions
  2. The EDA Mindset
  3. Univariate Analysis
  4. Bivariate Analysis
  5. Multivariate Analysis
  6. Groupby-Based Exploration Workflows
  7. Segmentation and Drill-Down
  8. Guarding Against Simpson's Paradox
  9. A Systematic EDA Checklist
  10. Hands-On: A Complete EDA Pass on a New Dataset
  11. Case Studies
  12. Common Misconceptions and Pitfalls
  13. Glossary
  14. Exercises
  15. Quiz
  16. Summary
  17. Further Reading

Learning Objectives#

By the end of this notebook, you will be able to:

  • Explain the goal and mindset of exploratory data analysis, distinct from confirmatory analysis
  • Perform univariate analysis on numeric and categorical variables using appropriate summaries
  • Perform bivariate analysis to examine relationships between pairs of variables, choosing techniques appropriate to variable type combinations
  • Perform multivariate analysis to examine relationships among three or more variables simultaneously
  • Use groupby-based workflows systematically to explore a dataset across multiple dimensions
  • Apply segmentation and drill-down techniques to investigate patterns hidden within an aggregate
  • Recognize and check for Simpson's Paradox before drawing conclusions from a dataset with subgroup structure
  • Apply a systematic EDA checklist to any new dataset

1. What EDA Is and Why It Comes Before Conclusions#

Exploratory Data Analysis (EDA) is the practice of systematically examining a dataset to understand its structure, patterns, anomalies, and relationships, before committing to any particular conclusion, model, or formal statistical test. The term and much of its modern practice trace back to statistician John Tukey, who argued that data analysis should begin with open-ended exploration rather than jumping directly to hypothesis confirmation.

This notebook sits at the intersection of everything covered so far: it uses the cleaned data from Notebook 4, the reshaping tools from Notebook 5, and the descriptive statistics and probability concepts from Notebook 6, applying them not as isolated techniques but as a coherent, iterative investigative process. Where Notebook 6 taught you how to compute a mean, a skewness, or a percentile, this notebook teaches you when and why to reach for each of them, and how to string them together into a genuine investigation.


2. The EDA Mindset#

2.1 Exploratory vs. Confirmatory Analysis#

Confirmatory analysis starts with a specific hypothesis and tests it rigorously (the subject of Notebook 10). Exploratory analysis starts with curiosity and an open mind, looking for patterns, surprises, and questions worth investigating further, without committing in advance to a specific conclusion. Both are essential, but conflating them, particularly treating an EDA-discovered pattern as if it had been rigorously confirmed, is a serious and common analytical error, discussed further in Section 12.

2.2 Iteration, Not a Linear Checklist#

Real EDA is rarely a single linear pass; it typically resembles a loop: look at a summary, notice something interesting or surprising, drill down, discover a new question, drill down again. The systematic checklist in Section 9 provides a starting structure, but genuine exploration means being willing to deviate from it whenever the data itself suggests a more interesting direction.

2.3 The Combination of Numbers and Visuals#

While this notebook focuses on the numeric and tabular side of EDA, visualizations (covered fully in Notebook 8) are inseparable from good exploratory practice in real work; a summary statistic can hide exactly the kind of structure a well-chosen plot reveals immediately, and vice versa. The two should generally be used together rather than viewed as alternatives.


3. Univariate Analysis#

3.1 Univariate Analysis of Numeric Variables#

Univariate analysis examines one variable at a time. For numeric variables, this means applying the toolkit from Notebook 6 systematically:

Python
import pandas as pd df = pd.read_csv("customer_data.csv") print(df["monthly_spend"].describe()) print(f"Skewness: {df['monthly_spend'].skew():.2f}") print(f"Kurtosis: {df['monthly_spend'].kurt():.2f}")

A useful habit is to run this full summary for every numeric column at once:

Python
numeric_cols = df.select_dtypes(include="number").columns summary = pd.DataFrame({ "mean": df[numeric_cols].mean(), "median": df[numeric_cols].median(), "std": df[numeric_cols].std(), "skew": df[numeric_cols].skew(), "missing_pct": df[numeric_cols].isna().mean() * 100 }) print(summary.round(2))

This single table immediately surfaces, for every numeric column at once, which ones are skewed (informing the mean-vs-median choice from Notebook 6, Section 2.5), which have meaningful missing data (a flag to revisit Notebook 4's cleaning decisions), and gives a first-pass sense of scale differences across variables.

3.2 Univariate Analysis of Categorical Variables#

For categorical variables, the equivalent starting point is frequency counts, not mean/median/std, which are not meaningful for nominal data (Notebook 0, Section 8.2):

Python
print(df["subscription_tier"].value_counts()) print(df["subscription_tier"].value_counts(normalize=True).round(3)) # as proportions

3.3 Cardinality Check#

Before deeper analysis, checking the cardinality (number of unique values) of each categorical column is a useful early step, since it flags columns that may need different treatment: an identifier-like column with very high cardinality (nearly one unique value per row) is generally not useful for the kind of grouping and segmentation covered later in this notebook, while a column with unexpectedly high cardinality for what should be a small, fixed category set can flag a data quality issue (echoing the inconsistent-category problem from Notebook 4, Section 6.3).

Python
categorical_cols = df.select_dtypes(include=["object", "category"]).columns for col in categorical_cols: print(f"{col}: {df[col].nunique()} unique values")

4. Bivariate Analysis#

4.1 Choosing the Right Technique by Variable Type Pair#

The appropriate bivariate technique depends on whether each of the two variables involved is numeric or categorical.

Variable 1Variable 2Appropriate Technique
NumericNumericCorrelation (Notebook 9), scatter plot (Notebook 8)
NumericCategoricalGrouped summary statistics (mean/median by group), box plot by group
CategoricalCategoricalCross-tabulation (Notebook 5, Section 8), grouped frequency counts

4.2 Numeric vs. Categorical: Grouped Summaries#

Python
grouped_summary = df.groupby("subscription_tier")["monthly_spend"].agg( ["mean", "median", "std", "count"] ) print(grouped_summary.round(2))

Expected output (illustrative):

code
mean median std count subscription_tier Basic 22.40 19.99 11.20 450 Premium 68.75 65.00 22.30 280 Pro 142.10 138.50 35.80 120

This directly reuses the groupby aggregation mechanics from Notebook 3, Section 4.1, but applied specifically as an exploratory technique: comparing central tendency and spread of a numeric variable across the levels of a categorical variable is one of the single most common and valuable bivariate EDA patterns.

4.3 Categorical vs. Categorical: Cross-Tabulation#

Directly reusing Notebook 5, Section 8:

Python
crosstab = pd.crosstab(df["region"], df["subscription_tier"], normalize="index") print(crosstab.round(2))

4.4 Numeric vs. Numeric: A Preview of Correlation#

A full treatment of correlation is reserved for Notebook 9, but a quick pairwise check is a standard part of any bivariate EDA pass:

Python
print(df[["monthly_spend", "account_age_months"]].corr())

5. Multivariate Analysis#

5.1 Why Move Beyond Two Variables#

Bivariate analysis (Section 4) can miss patterns that only appear when considering three or more variables jointly, a concern that becomes especially critical given Simpson's Paradox (Section 8). Multivariate analysis examines relationships among several variables at once, typically by combining grouping, aggregation, and visualization dimensions (color, facets, covered in Notebook 8) simultaneously.

5.2 Multi-Level Groupby as Multivariate Analysis#

The simplest form of multivariate EDA extends the grouped summary from Section 4.2 to multiple grouping variables at once:

Python
multi_grouped = df.groupby(["region", "subscription_tier"])["monthly_spend"].mean().unstack() print(multi_grouped.round(2))

This produces exactly the kind of MultiIndex-based, multi-dimensional summary covered in Notebook 5, Sections 6 and 7, now applied specifically as an exploratory tool to check whether a relationship observed in Section 4.2 (spend by tier) holds consistently across another dimension (region), or whether it varies meaningfully by region, a pattern worth investigating further if so.

5.3 Pairwise Relationships Across Many Variables at Once#

For a first-pass overview of relationships among several numeric variables simultaneously, a full correlation matrix (previewed here, covered fully in Notebook 9) or a pair plot (Notebook 8) provides a compact multivariate summary:

Python
numeric_cols = ["monthly_spend", "account_age_months", "num_support_tickets", "login_frequency"] print(df[numeric_cols].corr().round(2))

5.4 Conditional Multivariate Summaries#

Combining a numeric summary with two or more categorical grouping dimensions and an additional conditional filter is a common, powerful multivariate exploration pattern:

Python
high_tenure = df[df["account_age_months"] > 24] result = high_tenure.groupby(["region", "subscription_tier"])["monthly_spend"].agg(["mean", "count"]) print(result.round(2))

This narrows the multivariate analysis to a specific, meaningful subpopulation (long-tenured customers), directly illustrating the segmentation theme developed further in Section 7.


6. Groupby-Based Exploration Workflows#

6.1 A Repeatable Exploration Pattern#

A highly reusable EDA workflow: for any numeric metric of interest, systematically compute its summary statistics across every plausible categorical grouping variable in the dataset, scanning for the largest or most surprising differences:

Python
def explore_by_all_categoricals(df, numeric_col, categorical_cols): for cat_col in categorical_cols: print(f"\n--- {numeric_col} by {cat_col} ---") summary = df.groupby(cat_col)[numeric_col].agg(["mean", "median", "count"]) print(summary.round(2).sort_values("mean", ascending=False)) categorical_cols = ["region", "subscription_tier", "acquisition_channel"] explore_by_all_categoricals(df, "monthly_spend", categorical_cols)

This turns a manual, one-off groupby call (as in Section 4.2) into a systematic, repeatable scan across every relevant categorical dimension, surfacing patterns that a single, manually chosen grouping might miss entirely.

6.2 Ranking Groups by Variability, Not Just Level#

An often-overlooked but valuable groupby-based exploration: checking which groups have the most variable outcomes, not just the highest or lowest average, since high variability within a group can itself be an important, actionable finding (e.g., a region with inconsistent performance may indicate an operational problem worth investigating, distinct from a region that is simply, consistently low-performing):

Python
variability = df.groupby("region")["monthly_spend"].agg(["mean", "std"]) variability["coefficient_of_variation"] = (variability["std"] / variability["mean"] * 100).round(1) print(variability.sort_values("coefficient_of_variation", ascending=False))

This directly applies the coefficient of variation concept from Notebook 6, Section 3.5 as a groupby-based exploratory tool for comparing relative variability across groups on a fair, scale-independent basis.

6.3 Combining groupby With Filtration#

Recall groupby(...).filter(...) from Notebook 3, Section 4.3; it is a natural EDA tool for isolating groups that meet or fail to meet a threshold of interest, useful for quickly narrowing an exploration to the most relevant subset of groups:

Python
# Identify only regions with more than 50 customers, to avoid drawing # conclusions from groups with unreliably small sample sizes sufficiently_sized_regions = df.groupby("region").filter(lambda g: len(g) > 50)

This directly connects to a critical EDA discipline: always checking group sizes (Section 9) before comparing group-level statistics, since a group with very few observations can produce a mean or median that looks meaningfully different purely due to random sampling noise rather than a genuine underlying pattern.


7. Segmentation and Drill-Down#

7.1 The Drill-Down Pattern#

Drill-down is the practice of progressively narrowing an analysis from a broad aggregate view into more specific subgroups, precisely the technique that resolved the misleading dashboard scenario in Notebook 0, Section 9.1. A typical drill-down sequence:

  1. Start with an overall aggregate metric (e.g., overall average revenue)
  2. Break it down by one dimension (e.g., by region, as in Section 4.2)
  3. If a region looks unusual, break that region down further (e.g., by acquisition channel within that region)
  4. Continue narrowing until a specific, actionable, and well-understood pattern emerges, or until further narrowing no longer reveals new structure

7.2 A Worked Drill-Down Example#

Python
# Step 1: overall aggregate print(f"Overall average monthly spend: {df['monthly_spend'].mean():.2f}") # Step 2: break down by region by_region = df.groupby("region")["monthly_spend"].mean() print(by_region.round(2)) # Step 3: South region looks unusually low -- drill into it further south_data = df[df["region"] == "South"] by_channel_in_south = south_data.groupby("acquisition_channel")["monthly_spend"].mean() print(by_channel_in_south.round(2))

Each step in this sequence narrows the population under examination while asking the same underlying question ("what is driving this metric") at progressively finer granularity, directly following the workflow demonstrated in Notebook 0's retail revenue example (Section 7) taken one level deeper.

7.3 Segmentation as a Standing Analytical Frame#

Segmentation is the related but distinct practice of deliberately dividing a population into meaningful, often business-relevant groups (new vs. existing customers, high vs. low value, by acquisition channel) as a standing lens for viewing every metric, not just as a one-off drill-down triggered by a specific anomaly. A mature analytics practice typically maintains a small set of standard segments that most reports and dashboards are automatically broken down by, precisely to catch the kind of aggregate-masking problem described in Notebook 0's dashboard case study before it requires an ad hoc investigation to surface.


8. Guarding Against Simpson's Paradox#

8.1 Recap and Why It Belongs in This Notebook#

Notebook 0, Section 9.2 introduced Simpson's Paradox: a trend present in aggregated data can reverse when the data is broken into meaningful subgroups. EDA is precisely the discipline that catches this, since it is exactly the process of checking aggregate patterns against subgroup breakdowns before trusting them.

8.2 A Worked Numeric Demonstration#

Python
import pandas as pd # Simulated data: overall, treatment B looks better, but within each # severity subgroup, treatment A is actually better or equal data = pd.DataFrame({ "treatment": ["A", "A", "A", "A", "B", "B", "B", "B"], "severity": ["mild", "mild", "severe", "severe", "mild", "mild", "severe", "severe"], "recovered": [1, 1, 1, 0, 1, 1, 0, 0] }) print("Overall recovery rate by treatment:") print(data.groupby("treatment")["recovered"].mean()) print("\nRecovery rate by treatment, WITHIN each severity level:") print(data.groupby(["severity", "treatment"])["recovered"].mean().unstack()) print("\nCase counts by severity and treatment:") print(data.groupby(["severity", "treatment"]).size().unstack())

Expected output:

code
Overall recovery rate by treatment: treatment A 0.75 B 0.50 Recovery rate by treatment, WITHIN each severity level: treatment A B severity mild 1.0 1.0 severe 0.5 0.0 Case counts by severity and treatment: treatment A B severity mild 2 2 severe 2 2

In this constructed example, treatment A does look better both overall and within each severity subgroup here (a case designed to show consistency), but a subtle change to the proportion of severe cases in each treatment group (rather than the within-group recovery rates themselves) can flip the aggregate ranking even while every subgroup individually favors one treatment, which is the actual mechanism behind Simpson's Paradox: an uneven distribution of a confounding variable (severity) across the groups being compared (treatment), combined with that confounding variable also affecting the outcome.

8.3 The Standing Checklist Question#

Before trusting any aggregate comparison between groups (regions, treatments, cohorts, time periods), a standing EDA question should be: is there a plausible confounding variable that differs in composition between the groups being compared, and does breaking the comparison down by that variable change the conclusion? This single question, applied systematically, is the practical defense against Simpson's Paradox, and is precisely why Section 5.2's multi-level groupby and Section 7's drill-down technique are not optional refinements but core EDA discipline.


9. A Systematic EDA Checklist#

A structured starting sequence for any new dataset, synthesizing the techniques from this notebook and building directly on Notebook 4's cleaning validation (Section 8) and Notebook 2's inspection routine (Section 9):

  1. Shape and structure: .shape, .info(), .head() — confirm the dataset loaded as expected
  2. Missing data: .isna().sum() — confirm cleaning from Notebook 4 was applied, or identify what remains
  3. Univariate numeric summary: mean, median, std, skew for every numeric column (Section 3.1)
  4. Univariate categorical summary: value counts and cardinality for every categorical column (Section 3.2, 3.3)
  5. Key bivariate relationships: grouped summaries and cross-tabulations for variable pairs relevant to the business question (Section 4)
  6. Group size check: confirm no group being compared has a suspiciously small sample size (Section 6.3)
  7. Multivariate check: does a bivariate pattern hold consistently across a third dimension, or does it interact with it (Section 5, Section 8)?
  8. Drill-down on anomalies: for any group or pattern that looks unusual, narrow further to understand why (Section 7)
  9. Document open questions: EDA often raises more questions than it answers in a single pass; explicitly noting what remains uncertain or what would need further investigation is itself a valuable EDA output.

10. Hands-On: A Complete EDA Pass on a New Dataset#

This example applies the full checklist from Section 9 to a simulated e-commerce dataset from start to finish.

Python
import pandas as pd import numpy as np rng = np.random.default_rng(42) n = 1000 df = pd.DataFrame({ "customer_id": range(1, n + 1), "region": rng.choice(["North", "South", "East", "West"], size=n, p=[0.3, 0.2, 0.25, 0.25]), "acquisition_channel": rng.choice(["Organic", "Paid Search", "Social", "Referral"], size=n), "account_age_months": rng.integers(1, 60, size=n), "monthly_spend": np.round(rng.exponential(scale=40, size=n), 2) }) # Step 1-2: structure and missing data print(df.shape) print(df.isna().sum().sum()) # 0, confirming no missing data in this simulated set # Step 3: univariate numeric summary print(df[["account_age_months", "monthly_spend"]].agg(["mean", "median", "std", "skew"]).round(2)) # Step 4: univariate categorical summary print(df["region"].value_counts(normalize=True).round(2)) # Step 5: bivariate - spend by region print(df.groupby("region")["monthly_spend"].mean().round(2).sort_values(ascending=False)) # Step 6: group size check print(df.groupby("region").size()) # Step 7: multivariate - does the region pattern hold across acquisition channel? print(df.groupby(["region", "acquisition_channel"])["monthly_spend"].mean().unstack().round(2)) # Step 8: drill down on whichever region/channel combination looks most unusual # (inspected manually from the Step 7 output in a real analysis)

Expected output (abbreviated, will vary due to randomness):

code
(1000, 5) 0 mean median std skew account_age_months 29.85 30.0 17.24 0.02 monthly_spend 40.31 27.8 40.87 2.15 South 0.20 West 0.25 East 0.25 North 0.30 Name: region, dtype: float64 region East 42.42 West 41.05 North 39.87 South 38.14 Name: monthly_spend, dtype: float64

Interpretation: The monthly_spend skewness of 2.15 immediately flags it as strongly right-skewed (consistent with the exponential distribution used to simulate it, per Notebook 6, Section 8.3), meaning the median (27.8) rather than the mean (40.31) better represents a typical customer's spend, exactly the lesson from Notebook 6's support ticket case study. The region-level averages show only modest differences here, which is itself a legitimate and useful EDA finding (no dramatic regional disparity), and the multivariate breakdown by acquisition channel within region is the natural next step to check for the kind of interaction or Simpson's-Paradox-style reversal discussed in Section 8.


11. Case Studies#

11.1 Case Study: An EDA Pass That Caught a Data Quality Issue Before It Reached a Report#

An analyst performing a routine univariate cardinality check (Section 3.3) on a "country" column expected roughly 30 unique values but found 187. Investigating further revealed the same countries were entered inconsistently across multiple source systems (e.g., "USA", "U.S.A.", "United States"), a direct real-world instance of the inconsistent categorical text problem from Notebook 4, Section 6.3.

Diagnosis: Without this early cardinality check, a subsequent groupby-based regional analysis (Section 4.2, 6.1) would have silently fragmented what should have been a single "United States" group into several smaller, artificially distinct groups, understating the true size and revenue contribution of that market in any resulting report.

Lesson: A cardinality check, taking seconds to run, caught a data quality issue that would otherwise have propagated invisibly into every downstream grouped analysis; this is precisely why Section 9's systematic checklist places univariate structural checks before any bivariate or multivariate analysis is attempted.

11.2 Case Study: A Marketing Channel Comparison Reversed by Drill-Down#

An aggregate analysis shows that customers acquired through "Paid Search" have a higher average lifetime value than those acquired through "Organic" search, leading to a recommendation to increase paid search budget. Following the drill-down pattern from Section 7.2, an analyst breaks this comparison down further by account tenure and discovers that among customers with more than 12 months of tenure specifically, Organic customers actually have a higher average lifetime value; the aggregate result was driven by a recent, large influx of new Paid Search customers who had not yet had time to churn, a group not present in comparable numbers in the Organic channel's mix.

Diagnosis: This is a real-world instance of the Simpson's-Paradox-style confounding described in Section 8: tenure (which affects lifetime value) was distributed very differently between the two channels being compared, and the aggregate comparison, without controlling for tenure, produced a misleading ranking.

Lesson: Any comparison between acquisition channels, cohorts, or other groups whose composition might differ on a variable that also affects the outcome (here, tenure) should be checked via the multivariate/drill-down techniques from Sections 5 and 7 before being used to justify a resource allocation decision as consequential as a budget shift.

11.3 Case Study: Group Size Blindness Producing an Unreliable "Top Performer"#

A sales dashboard ranks regional sales reps by average deal size and highlights the "top performer," who has an average deal size dramatically higher than everyone else. Applying the group size check from Section 6.3 reveals this rep has closed only 2 deals total, compared to 40-60 for most other reps, meaning their average is based on a tiny, noisy sample rather than a genuinely superior, consistent pattern.

Diagnosis: A groupby-based average, computed and ranked without any accompanying check of the underlying group size, treated a statistically unreliable estimate (from n=2) as directly comparable to well-supported estimates (from n=40-60), producing a "top performer" ranking driven substantially by chance rather than genuine, replicable performance.

Lesson: Every groupby-based comparison should be accompanied by, at minimum, a glance at group sizes (.size() or .count(), Section 6.3), and ideally a minimum sample size threshold (via .filter(), Section 6.3) before group-level rankings are presented as reliable, actionable findings.


12. Common Misconceptions and Pitfalls#

MisconceptionReality
"EDA is just a quick, informal first look before the 'real' analysis begins."EDA is itself a rigorous, structured discipline (Section 9's checklist) and frequently surfaces the most consequential findings of an entire analysis, as shown in every case study in this notebook.
"A pattern discovered during EDA is already a confirmed, reliable finding."EDA is exploratory, not confirmatory (Section 2.1); a pattern noticed during EDA should generally be treated as a hypothesis worth formally testing (Notebook 10), not a settled conclusion, especially if it will inform a major decision.
"If two groups have different average outcomes, that difference is automatically meaningful and genuine."Without checking group sizes (Section 6.3) and considering potential confounding variables (Section 8), an observed difference can be driven by random noise or by an uneven distribution of a third, unaccounted-for variable.
"Categorical cardinality checks are a minor, skippable formality."An unexpectedly high cardinality count is often the first, fastest signal of a real data quality problem, as shown in Section 11.1, and can silently distort every subsequent grouped analysis if missed.
"A comparison that holds in the aggregate will hold in every meaningful subgroup."This is precisely the failure mode of Simpson's Paradox (Section 8), directly illustrated by the marketing channel case study in Section 11.2, where drilling down reversed the aggregate conclusion entirely.
"The goal of EDA is to find the answer, not to find more questions."A mature EDA process often concludes with a well-documented set of open questions and hypotheses worth further investigation (Section 9, step 9), not necessarily a single final answer in one pass.

13. Glossary#

TermDefinition
Exploratory Data Analysis (EDA)The practice of systematically examining a dataset to understand its structure, patterns, and relationships before drawing conclusions
Univariate analysisExamining a single variable in isolation
Bivariate analysisExamining the relationship between two variables
Multivariate analysisExamining relationships among three or more variables simultaneously
CardinalityThe number of unique values present in a column
Drill-downProgressively narrowing an analysis from a broad aggregate into more specific subgroups to understand what is driving a pattern
SegmentationDeliberately dividing a population into meaningful, often business-relevant groups as a standing lens for analysis
Confounding variableA variable that differs in distribution between the groups being compared and also affects the outcome, capable of producing a misleading aggregate comparison
Simpson's ParadoxA phenomenon where a trend present in aggregated data reverses when the data is broken into meaningful subgroups

14. Exercises#

Exercise 1 (Conceptual)#

Explain the difference between exploratory and confirmatory analysis, and describe a specific risk of treating an EDA finding as if it were confirmatory.

<details> <summary>Solution</summary>

Exploratory analysis (Section 2.1) is open-ended investigation aimed at discovering patterns and generating hypotheses, without a predetermined hypothesis being tested; confirmatory analysis formally tests a specific, pre-specified hypothesis using rigorous statistical methods (Notebook 10). The specific risk of treating an EDA finding as confirmatory is that patterns discovered by looking at many possible relationships in a dataset (as EDA encourages) are more likely to include some that arise purely from random chance, particularly when many different groupings or variable pairs are examined, as in Section 6.1's systematic scan across all categorical columns; presenting such a pattern as a confirmed, reliable finding without a proper formal test (which accounts for this multiple-comparisons risk, touched on further in Notebook 10) risks acting on noise rather than a genuine, replicable pattern.

</details>

Exercise 2 (Conceptual)#

A dashboard shows that Region X has the highest average customer satisfaction score of all regions. Before accepting this as a genuine finding, list three specific checks from this notebook you would perform.

<details> <summary>Solution</summary>

Three reasonable checks: (1) Group size check (Section 6.3) — confirm Region X has a comparably large and reliable sample size relative to other regions, not a small handful of unusually satisfied customers driving an unstable average, echoing the sales rep case study in Section 11.3. (2) Confounding variable / Simpson's Paradox check (Section 8) — break the comparison down by a plausible confounding variable (such as customer tenure, acquisition channel, or product mix) to confirm Region X's advantage holds within meaningful subgroups, not just in aggregate, echoing the marketing channel case study in Section 11.2. (3) Categorical cardinality / data quality check (Section 3.3) on the region field itself — confirm "Region X" is not accidentally fragmenting or being fragmented from other regions due to inconsistent labeling, echoing the country-field case study in Section 11.1.

</details>

Exercise 3 (Coding)#

Given a DataFrame df with columns department, employee_level, and salary, write code implementing the systematic groupby exploration pattern from Section 6.1, checking average salary broken down separately by department and by employee_level, and include a group size column in each result.

<details> <summary>Solution</summary>
Python
import pandas as pd df = pd.DataFrame({ "department": ["Sales", "Sales", "Engineering", "Engineering", "Sales", "Engineering"], "employee_level": ["Junior", "Senior", "Junior", "Senior", "Senior", "Junior"], "salary": [55000, 78000, 65000, 98000, 82000, 68000] }) for group_col in ["department", "employee_level"]: print(f"\n--- Salary by {group_col} ---") summary = df.groupby(group_col)["salary"].agg(mean="mean", median="median", n="count") print(summary.round(2))

Including the n (count) column directly alongside the mean and median, per Section 6.3, ensures that any group with a suspiciously small sample size is immediately visible alongside its summary statistic, rather than requiring a separate lookup.

</details>

Exercise 4 (Applied Thinking)#

An aggregate analysis shows that a new product feature increased average user engagement across the platform. Before recommending a full rollout, describe a drill-down and multivariate investigation plan, referencing specific sections of this notebook, that would give you confidence the result is not a Simpson's-Paradox-style artifact.

<details> <summary>Solution</summary>

A reasonable plan: first, break the engagement comparison down by user segment (e.g., new vs. existing users, or by platform/device type), per the drill-down pattern in Section 7.2, to confirm the increase holds consistently within each segment rather than being driven by a shift in the mix of users exposed to the feature (for example, if the feature happened to be shown disproportionately to already highly-engaged users). Second, apply the multivariate groupby technique from Section 5.2 to check engagement by feature exposure combined with a plausible confounding variable such as tenure or prior engagement level, directly following the standing checklist question from Section 8.3: does a plausible confounding variable differ in composition between the exposed and unexposed groups, and does controlling for it change the conclusion? Third, perform a group size check (Section 6.3) on each subgroup examined, to ensure the segment-level comparisons are based on adequately sized samples and not vulnerable to the kind of small-sample noise illustrated in Section 11.3. Only after this multivariate, drill-down investigation holds up would the aggregate finding merit the confidence needed to justify a full rollout, and even then, a formal statistical test (Notebook 10) would typically be the appropriate final confirmatory step before treating it as a fully established result.

</details>

15. Quiz#

Q1. What is the primary distinction between exploratory and confirmatory analysis? a) Exploratory analysis uses larger datasets b) Exploratory analysis is open-ended investigation to discover patterns, while confirmatory analysis formally tests a pre-specified hypothesis c) They are the same process with different names d) Confirmatory analysis never uses statistics

Q2. Why is checking categorical cardinality an important early EDA step? a) It has no real analytical value, only cosmetic interest b) It can reveal data quality issues, such as inconsistent category labeling, before they distort downstream grouped analysis c) It is only relevant for numeric columns d) It replaces the need for any further analysis

Q3. What does the drill-down technique involve? a) Combining multiple unrelated datasets into one b) Progressively narrowing an analysis from an aggregate view into more specific subgroups to understand what is driving a pattern c) Removing all categorical variables from a dataset d) Converting long-format data to wide format

Q4. Why is a group size check important before comparing group-level averages? a) Group size never affects the reliability of an average b) A group with a very small sample size can produce an average that looks meaningfully different due to random noise rather than a genuine pattern c) It is only relevant for categorical variables d) Larger groups always have higher averages

Q5. True or False: If an aggregate comparison between two groups shows Group A outperforming Group B, this conclusion is guaranteed to hold within every meaningful subgroup of the data.

<details> <summary>Answers</summary>
  1. b) Exploratory analysis is open-ended investigation to discover patterns, while confirmatory analysis formally tests a pre-specified hypothesis
  2. b) It can reveal data quality issues, such as inconsistent category labeling, before they distort downstream grouped analysis
  3. b) Progressively narrowing an analysis from an aggregate view into more specific subgroups to understand what is driving a pattern
  4. b) A group with a very small sample size can produce an average that looks meaningfully different due to random noise rather than a genuine pattern
  5. False — this is precisely the risk of Simpson's Paradox (Section 8), directly illustrated by the marketing channel case study in Section 11.2
</details>

16. Summary#

  • EDA is a systematic, iterative discipline for understanding a dataset's structure and relationships before drawing conclusions, distinct from and preceding the confirmatory statistical testing covered in Notebook 10.
  • Univariate analysis applies appropriate summaries (numeric statistics or categorical frequency counts) to one variable at a time, with cardinality checks serving as an important early data quality signal.
  • Bivariate analysis technique choice depends on the combination of variable types involved: numeric-numeric, numeric-categorical, or categorical-categorical.
  • Multivariate analysis, often implemented via multi-level groupby, checks whether bivariate patterns hold consistently across additional dimensions, which is essential for catching Simpson's Paradox.
  • Groupby-based exploration workflows can be systematized into repeatable scans across every relevant categorical dimension, and should always be accompanied by a check of underlying group sizes.
  • Drill-down and segmentation provide the practical technique for investigating and explaining anomalies or surprises discovered during broader exploration.
  • A standing discipline of checking for confounding variables and subgroup consistency is the practical defense against Simpson's Paradox, and should be applied before any consequential decision is made based on an aggregate comparison.

17. Further Reading#

  • John Tukey, Exploratory Data Analysis (1977) — the foundational text that established EDA as a distinct discipline
  • David Spiegelhalter, The Art of Statistics: Learning from Data
  • Pandas official documentation on groupby: https://pandas.pydata.org/docs/user_guide/groupby.html
  • Roger Peng and Elizabeth Matsui, The Art of Data Science — a practical treatment of the EDA process and mindset

Next Up#

Notebook 8: Data Visualization for EDA — Matplotlib and Seaborn fundamentals, choosing the right plot type for a given variable combination, and distribution and relationship plots, providing the visual counterpart to the numeric and tabular EDA techniques developed in this notebook.


Course: Data Analytics | Notebook 7 of 13

Knowledge Checkpoint

Exploratory Data Analysis Techniques Checkpoint

Q1.What is Simpson's Paradox in exploratory data analysis?
AA statistical phenomenon where a trend or correlation observed in several individual sub-groups disappears or reverses when the groups are combined.
BWhen missing data exceeds 50%.
CWhen correlation equals exactly 1.0.
DWhen variance is larger than the mean.
Q2.What is the primary objective of Univariate Analysis during EDA?
ATo understand the distribution, central tendency, spread, outliers, and data types of each individual variable in isolation.
BTo train a machine learning classifier.
CTo compute pairwise correlation matrices.
DTo merge multiple database tables.
Q3.Which visualization and statistical technique is most suitable for Bivariate Analysis between a Continuous numeric variable and a Categorical group variable?
ABox plots / Violin plots and group aggregations (or ANOVA / t-tests).
BScatter plot with linear regression line.
CChi-Square contingency table heatmap.
DPie chart.
Track Your Learning

Finished studying this notebook?

Mark this guide as completed to update your course progress roadmap.