DSM
70 XP
35 minsIntermediate70 XP

Univariate Analysis

'Average salary: ₹18 lakh' — technically true at a company where the median engineer earns ₹9 lakh and three founders earn crores. One column, one number, and the story is already wrong. Univariate analysis is learning to see a whole distribution where amateurs see an average — and it's the level of EDA where most numeric lies are either caught or committed.

What you'll learn

  • Summarise numeric columns with centre, spread, AND shape — not just a mean
  • Diagnose skew from mean-vs-median and quantiles
  • Choose honest summaries: median/IQR for skewed data, mean/std for symmetric
  • Read categorical columns via value_counts (with normalize=True), nunique, and the long tail
  • Spot distribution red flags: spikes at defaults, impossible values, unexpected modality

What

Univariate analysis examines one column at a time: for numeric columns, the centre (mean, median), spread (std, IQR, range), and shape (skew, modality, outliers); for categorical columns, the frequency table, cardinality, and balance. The tools are describe, quantile, value_counts, nunique — plus the judgement of which summary honestly represents which shape.

Why

Every downstream statistic inherits the distribution's quirks. Means mislead on skew; standard deviations mislead with outliers; a 'top category' means little in a column that's 90% one value. Bivariate and multivariate work built on misread columns is confidently wrong — this level is the foundation.

Where it's used

The first pass of every EDA, sanity checks before dashboards quote any average, feature understanding before modelling (skew and rare categories drive preprocessing), and data drift monitoring in production.

Where this runs in production

NumbeoMedian, not mean, for cost of living

Salary and rent statistics are reported as medians because both are heavily right-skewed — a handful of penthouse rents would make the 'average' describe nobody's reality.

AmazonDelivery-time distributions

Operations tracks the P90 and P99 of delivery time, not the mean — the promise 'delivered by tomorrow' lives in the tail of the distribution, and means hide tails.

LinkedInFeature drift monitoring

Production ML systems monitor each feature's univariate distribution over time; a shift in a column's shape (new spike, vanished category) flags upstream breakage before model quality craters.

Theory

The core ideas, in plain language.

Key Concept
Three questions per numeric column

Centre: what's typical? (mean, median). Spread: how much do values vary? (std, IQR, min–max). Shape: how are values arranged? (symmetric or skewed, one hump or several, outliers present?). A column isn't understood until all three are answered — and shape is the one that decides whether the other two were measured honestly.

s.describe()
# count, mean, std, min, 25%, 50% (median), 75%, max

s.quantile([0.01, 0.05, 0.5, 0.95, 0.99])   # tail detail
s.skew()                                     # >0 right skew, <0 left

describe() answers centre and spread in one call and hints at shape: compare mean to 50%, and min/max to the quartiles. The quantile call zooms into the tails — where delivery promises, risk, and outliers live. skew() quantifies asymmetry.

Key Concept
The mean–median gap is a skew detector

In a symmetric distribution mean ≈ median. Extreme values drag the MEAN toward themselves but barely move the MEDIAN — so mean ≫ median means right skew (income, prices, durations: most values modest, few huge), mean ≪ median means left skew. Rule of practice: report medians and IQRs for skewed columns, means and stds for symmetric ones — and when in doubt, both.

# Categorical columns: frequency, share, cardinality
s.value_counts()                  # counts, descending
s.value_counts(normalize=True)    # shares — always look at both
s.nunique()                       # cardinality
s.value_counts().head(10)         # the head; the tail is the rest

For categoricals the 'distribution' is the frequency table. normalize=True turns counts into shares — '4,812 orders from Delhi' means little until it's '61% of all orders'. Cardinality tells you whether this is a 5-value plan column or a 40,000-value free-text field wearing a category's clothes.

Balance matters as much as the top value: a category column that's 95% one value carries little information and will dominate any naive percentage; a long tail of hundreds of rare values usually needs grouping into 'other' before analysis. And a distribution's MODALITY — one hump or two — is a segmentation clue: bimodal session durations often mean two behaviours (browsers vs buyers) sharing one column.
Watch out
Spikes are messages

A suspicious concentration at one exact value is rarely behaviour: a spike at 0 may be 'never activated' coded as zero; at -999 or 1900-01-01, a sentinel for missing; at exactly 100, a cap or data-entry default; at round numbers, human estimation. value_counts().head() on a NUMERIC column is the quick spike detector. Every spike gets the artifact interrogation from the workflow lesson before it's allowed to mean anything.

Analogy: A distribution is a crowd, not a person

Asking 'what's the average?' of a column is like describing a crowd by one representative. Fine if the crowd is uniform office workers (symmetric: the mean person exists). Absurd at a stadium mixing toddlers and athletes (bimodal: the 'average' person is neither). Misleading if three billionaires walk in (skew: the mean wealth describes no one present). Univariate analysis is looking at the actual crowd before choosing who speaks for it.

Visual Learning

See the concept, then explore it.

Reading one column honestly

Click through — the column's type and shape decide which summaries you may trust.

Worked Examples

Watch it built up, one line at a time.

Very Easydescribe, then actually read it

Order values through the three-question lens.

Step 1 of 3

Seven orders. Six cluster near 240; one is 3800.

Code
01import pandas as pd
02s = pd.Series([220, 250, 240, 260, 230, 245, 3800])
Practice Coding

Your turn — write the code.

Your task

Profile a salary column and a department column: detect the skew, choose the honest centre, and summarise the categorical with shares.

Expected output
76.8 37.0
True
{'eng': 0.67, 'sales': 0.22, 'hr': 0.11}

Write your solution in the editor on the right, then hit Run.

Exercises

Prove it. Reach 80% to complete the lesson.

Mastery Gate0% / 80% required
Easy0/2 solved

A column's mean is 76.8 and its median is 37. What does this indicate?

Why look at value_counts(normalize=True) and not just value_counts()?

Medium0/2 solved

Session durations show the value 0.0 occurring in exactly 50% of rows, with the rest spread continuously between 2 and 60 minutes. Best interpretation?

ScenarioA product's ratings average exactly 3.0. The PM concludes 'users feel neutral about the product' and deprioritises it. The value_counts: {1: 40%, 2: 8%, 4: 10%, 5: 42%}.

What did the PM miss?

Hard0/2 solved

For the wait-times Series, print three numbers on one line each: the median, the P90 (90th percentile), and the share of values strictly above 10 (rounded to 2 decimals). s = pd.Series([2, 3, 4, 3, 5, 4, 6, 3, 12, 18, 4, 5])

Tail metrics:quantile(0.9) gives the P90 (11.4); the boolean mean gives the share above threshold (2 of 12 → 0.17)
Centre:The median 4.0 describes the typical wait — the two long waits (12, 18) barely move it

For a right-skewed latency column, why does the ops team track P90/P99 rather than the mean?

Complete 80% more exercises to unlock.
Interview Prep

How this shows up in real interviews.

How do you summarise a numeric column you've never seen, and how do you decide mean vs median?

Show model answer

I answer three questions in order: centre, spread, shape — because shape determines whether the first two were measured honestly. Mechanically: describe() for the overview, then the mean–median comparison as my skew detector, quantiles at 1/5/95/99% for tail behaviour, and value_counts().head() even on numeric columns to catch spikes at exact values. The mean-vs-median decision follows the shape: symmetric distributions → mean and std are efficient and honest; skewed distributions → median and IQR, because a few extremes make the mean describe nobody (the classic salary column). I also check modality — a bimodal column has no meaningful centre at all, and the summary becomes 'two populations: X% here, Y% there', which is a segmentation lead. And for duration-like columns I add P90/P99, because operational promises live in tails. The one-sentence version: never quote a centre until you've seen the shape.

What do you look for in a categorical column beyond the most common value?

Show model answer

Four things. Cardinality first — nunique tells me whether it's a genuine categorical (6 plans) or free text in disguise (40,000 'categories'), which changes everything downstream. Balance second — value_counts with normalize: a column that's 95% one value carries little signal and will dominate any naive rate; conversely near-uniform categories mean no segment stands out. The tail third — hundreds of rare values usually need grouping into 'other' before analysis, and the tail is also where string-cleaning failures hide ('Delhi'/'delhi' variants inflating cardinality — a sign to loop back to cleaning). Unexpected values fourth — categories that shouldn't exist ('test', 'TBD', empty strings) are quality findings. I report top-k with shares plus the tail's aggregate share: 'Delhi 61%, Pune 22%, 14 others 17%' — that sentence carries concentration, diversity, and completeness, where a bare mode ('most orders: Delhi') carries almost nothing.

Give examples of univariate red flags and what each usually means.

Show model answer

Spikes at exact values in continuous data: 0 is often 'never happened' coded as zero; -999, 9999, or 1900-01-01 are missing-value sentinels; exact caps (100, 255) suggest truncation at a system limit; round-number clustering suggests human estimation rather than measurement. Impossible values: negative durations, ages over 130, percentages over 100 — data errors by definition. Mean–median divergence: skew, so mean-based reporting is at risk. Bimodality: two populations sharing one column — mixed device types, mixed user tiers — and every whole-column statistic quietly averages the two. Suspicious completeness: a std of zero (constant column, no information) or perfectly uniform categories (synthetic or test data). Cardinality anomalies: 47 spellings of 30 cities is a cleaning failure; nunique equal to row count in a supposed category means it's an ID. Each red flag has the same follow-up: interrogate the mechanism before letting the column into bivariate work — because the next lesson's correlations and group comparisons inherit every one of these pathologies silently.

Common Mistakes to Avoid

1) Quoting a mean without ever comparing it to the median — skew goes undetected. 2) Reporting centre without spread: 'average 240' hides whether values run 230–250 or 10–3800. 3) Skipping value_counts on numeric columns and missing sentinel spikes (0, -999). 4) Treating a bimodal column's mean as 'typical' when nobody sits there. 5) Reading categorical counts without shares (or shares without counts). 6) Ignoring cardinality — analysing free text as if it were 6 tidy categories. 7) Using means for duration/latency promises when the tail (P90/P99) is what breaks. 8) Deleting spike values before asking what they encode.

Ask the AI Tutor

Try these prompts in the AI Tutor panel: • 'ELI5: the crowd-not-a-person view of distributions.' • 'Give me five describe() outputs and I'll diagnose the shape of each.' • 'Quiz me: mean/std or median/IQR for columns you invent?' • 'Show me how a sentinel spike distorts every summary statistic.' • 'Interview mode: I summarise a column, you find what I failed to check.'

Glossary

Univariate — one column at a time. Centre — typical value: mean (moment-based) or median (rank-based). Spread — variability: std, IQR (75th−25th percentile), range. Shape — the distribution's form: skew, modality, outliers. Right/left skew — long tail toward high/low values; drags the mean that direction. Bimodal — two humps; usually two populations in one column. Percentile / quantile — the value below which X% of data falls (P90 = quantile(0.9)). Sentinel — a code standing for 'missing/none' (0, -999). Cardinality — number of distinct values (nunique). Mode — most frequent value.

Recommended Resources

• Docs: pandas describe/quantile/value_counts references — small APIs, large mileage. • Read: any primer on 'why medians for income statistics', then a percentile-based SLO/SLA explainer (Google's SRE book chapter on monitoring is excellent) for the tail-thinking habit. • Practice: profile 5 numeric and 5 categorical columns of any public dataset; for each write ONE honest summary sentence and note which statistic you refused to use and why. • Next in DSM: columns understood alone — Bivariate Analysis asks how they move together: correlation, group comparisons, and cross-tabs.

Recap

✓ Three questions per numeric column: centre, spread, shape — and shape rules on the honesty of the other two. ✓ Mean ≫ median = right skew → report median/IQR; symmetric → mean/std; durations → add P90/P99 for the tail. ✓ Spikes at exact values are codes (sentinels, defaults, caps), not behaviour — interrogate before including or excluding. ✓ Bimodality means two populations share the column; the 'centre' describes neither, and segmentation is the next move. ✓ Categoricals: value_counts with counts AND shares, nunique for cardinality, and mind the long tail. Next up: Bivariate Analysis. Each column understood alone — now the questions that drive most findings: does X differ by Y, and how strongly do two columns move together?

scratchpad — preview this lesson's challenge anytime
univariate_practice.pyPython
Ready
Output

Run your code to see the output here.