0Pricing
Pandas & NumPy Academy · Lesson

Univariate Analysis

Analyse each column independently: plot distributions for numerics and value counts for categoricals, note outliers and skewness.

Univariate Analysis is a free Pandas & NumPy Academy lesson on CoddyKit — lesson 2 of 4. You can read the complete lesson below for free — then practise it hands-on in the browser with a built-in code editor and a 24/7 AI tutor. It is part of the Pandas & NumPy Academy learning path, one of 4 lessons in the course, and your progress syncs across the web and the CoddyKit app.

What Is Univariate Analysis?

Univariate analysis examines one column at a time in isolation, ignoring relationships between columns. The goal is to understand each variable's distribution, detect outliers, identify skewness, and spot data quality issues before any modelling begins. Univariate analysis differs for numeric and categorical columns — numerics need distribution plots and summary statistics, while categoricals need frequency counts and proportions.

import pandas as pd
import seaborn as sns

df = sns.load_dataset('titanic')
numeric_cols = df.select_dtypes('number').columns.tolist()
categoric_cols = df.select_dtypes('object').columns.tolist()

print('Numeric columns:', numeric_cols)
print('Categorical columns:', categoric_cols)

Histograms for Numeric Columns

Plot a histogram for each numeric column to see the shape of its distribution. Look for symmetry vs. skewness (tail on one side), modality (one peak vs. several), and obvious anomalies (values at extreme ends that seem implausible). In Pandas, df.hist() creates a quick multi-column histogram grid without writing a loop, but Seaborn's histplot gives finer control for individual columns.

import pandas as pd
import matplotlib.pyplot as plt
import seaborn as sns

df = sns.load_dataset('titanic')

# Quick multi-column histogram grid
numeric = df.select_dtypes('number')
numeric.hist(bins=20, figsize=(12, 8), layout=(2, 3), color='steelblue', edgecolor='white')
plt.suptitle('Univariate Distributions (Numeric Columns)', y=1.02)
plt.tight_layout()
plt.show()

Summary Statistics for Numeric Columns

For each numeric column, compute and compare mean vs. median. When mean > median significantly, the distribution is right-skewed (long right tail, common for income and price data). When mean < median, it is left-skewed. Also check standard deviation relative to the mean: a std larger than the mean for a non-negative variable is a sign of high variability or outliers. Compute skewness directly with df.skew().

import pandas as pd
import seaborn as sns

df = sns.load_dataset('titanic')
numeric = df.select_dtypes('number')

summary = pd.DataFrame({
    'mean': numeric.mean(),
    'median': numeric.median(),
    'std': numeric.std(),
    'skewness': numeric.skew(),
    'missing_pct': (numeric.isna().sum() / len(df) * 100).round(1)
}).round(2)

print(summary)

Box Plots for Outlier Detection

Box plots are the quickest visual tool for spotting outliers in numeric columns. Any point beyond the whiskers (1.5×IQR from Q1 or Q3) is plotted individually and flagged as a potential outlier. A column with many outlier points warrants investigation: are they data entry errors, legitimate extreme values, or evidence of a non-normal distribution? Box plots also reveal right or left skew from the asymmetric position of the median inside the box.

import pandas as pd
import matplotlib.pyplot as plt
import seaborn as sns

df = sns.load_dataset('titanic')

fig, axes = plt.subplots(1, 3, figsize=(14, 5))

for ax, col in zip(axes, ['age', 'fare', 'sibsp']):
    df[[col]].boxplot(ax=ax)
    ax.set_title(f'Box Plot: {col}')

plt.tight_layout()
plt.show()

IQR-Based Outlier Counts

The IQR (Interquartile Range) method defines outliers as values below Q1 - 1.5×IQR or above Q3 + 1.5×IQR. You can compute this programmatically to count and inspect outliers in every numeric column without plotting. This is useful in automated pipelines where you need to log anomaly counts rather than generate charts. Deciding what to do with outliers — remove, cap, or flag — should be a deliberate choice informed by domain knowledge.

import pandas as pd
import seaborn as sns

df = sns.load_dataset('titanic')
numeric = df.select_dtypes('number')

Q1 = numeric.quantile(0.25)
Q3 = numeric.quantile(0.75)
IQR = Q3 - Q1

lower = Q1 - 1.5 * IQR
upper = Q3 + 1.5 * IQR

outlier_counts = ((numeric < lower) | (numeric > upper)).sum()
print('Outlier counts per column:')
print(outlier_counts[outlier_counts > 0])

Value Counts for Categorical Columns

For each categorical column, call value_counts() to see how observations are distributed across categories. Always check: does any single category dominate (>80%)? This causes class imbalance in classification tasks. Are there rare categories with only 1-2 observations (typos or data entry errors)? Does the distribution match business expectations (e.g. a 'country' column that shows most orders from an unexpected country)?

import pandas as pd
import seaborn as sns

df = sns.load_dataset('titanic')

for col in ['sex', 'embarked', 'class', 'who']:
    counts = df[col].value_counts(dropna=False)
    pct = (counts / len(df) * 100).round(1)
    result = pd.DataFrame({'count': counts, 'pct%': pct})
    print(f'\n--- {col} ---')
    print(result)

Bar Charts for Categorical Variables

Visualise categorical value counts as bar charts using sns.countplot or by calling value_counts().plot(kind='bar'). Sort bars from most to least frequent so the viewer can immediately see dominant categories. For binary variables (yes/no, male/female), a pie chart is acceptable — but for more than 3 categories, bar charts are always clearer. Rotate tick labels 45 degrees when category names are long.

import pandas as pd
import matplotlib.pyplot as plt
import seaborn as sns

df = sns.load_dataset('titanic')

fig, axes = plt.subplots(1, 2, figsize=(12, 5))

sns.countplot(data=df, x='embarked', order=df['embarked'].value_counts().index, ax=axes[0])
axes[0].set_title('Embarkation Port Counts')

sns.countplot(data=df, x='class', order=['First', 'Second', 'Third'], ax=axes[1])
axes[1].set_title('Passenger Class Counts')

plt.tight_layout()
plt.show()

Detecting Skewness and Applying Transforms

Highly right-skewed numeric columns (skewness > 1.5) often benefit from a log transform to make them more symmetric. This is important for many statistical tests and some ML algorithms that assume normality. Apply np.log1p() (log(x+1), safe for values near zero) and re-check skewness. Compare histograms before and after to confirm the distribution became more bell-shaped.

import pandas as pd
import numpy as np
import matplotlib.pyplot as plt
import seaborn as sns

df = sns.load_dataset('titanic')

fig, axes = plt.subplots(1, 2, figsize=(10, 4))

sns.histplot(df['fare'], bins=30, kde=True, ax=axes[0])
axes[0].set_title(f'fare (skew={df["fare"].skew():.2f})')

log_fare = np.log1p(df['fare'])
sns.histplot(log_fare, bins=30, kde=True, ax=axes[1], color='coral')
axes[1].set_title(f'log1p(fare) (skew={log_fare.skew():.2f})')

plt.tight_layout()
plt.show()

Checking for Zero Variance Columns

A column with zero variance (all values are identical) provides no information to any model and should be dropped. A column with near-zero variance (99% of rows have the same value) is similarly useless. Compute variance with df.var() and filter. Also check for columns where nunique() == len(df) — these are likely ID columns that should not be used as features but may be useful as row identifiers.

import pandas as pd
import seaborn as sns

df = sns.load_dataset('titanic')
numeric = df.select_dtypes('number')

# Zero-variance columns
zero_var = numeric.columns[numeric.var() == 0].tolist()
print('Zero-variance columns:', zero_var)

# Near-zero variance (std < 0.01)
nzv = numeric.columns[numeric.std() < 0.01].tolist()
print('Near-zero variance:', nzv)

# Likely ID columns (all unique values)
id_candidates = [c for c in df.columns if df[c].nunique() == len(df)]
print('Likely ID columns:', id_candidates)

Univariate Analysis Automation Loop

Rather than repeating the same analysis manually for each column, write a loop that iterates over all numeric columns and prints key statistics in a structured format. This makes it easy to scan dozens of columns quickly and flag those that need attention. The output can be saved to a CSV file as part of a pipeline audit log that stakeholders can review before data is used in modelling.

import pandas as pd
import seaborn as sns

df = sns.load_dataset('titanic')
numeric = df.select_dtypes('number')

rows = []
for col in numeric.columns:
    s = df[col]
    Q1, Q3 = s.quantile(0.25), s.quantile(0.75)
    IQR = Q3 - Q1
    n_outliers = ((s < Q1 - 1.5*IQR) | (s > Q3 + 1.5*IQR)).sum()
    rows.append({
        'column': col,
        'missing_pct': round(s.isna().mean() * 100, 1),
        'mean': round(s.mean(), 2),
        'std': round(s.std(), 2),
        'skew': round(s.skew(), 2),
        'outliers': int(n_outliers)
    })

report = pd.DataFrame(rows)
print(report.to_string(index=False))

Documenting Univariate Findings

After completing univariate analysis, document your findings systematically. For each column note: the distribution shape (skewed, bimodal, normal-ish), missing value percentage and planned imputation strategy, outlier count and decision (cap, remove, flag), and any suspicious values requiring domain clarification. This documentation becomes the data quality log that guides the cleaning steps and protects decisions from being forgotten or contested later.

Quick Check

Test your understanding of univariate analysis from this lesson.

Lesson Recap

In this lesson you learned: histograms reveal distribution shape for numeric columns, box plots and IQR fencing identify outliers, and value_counts reveals category frequency for categorical columns. Automating these checks in a loop creates a reusable quality report. Next up we explore bivariate and correlation analysis — understanding relationships between pairs of columns.

Frequently asked questions

Is the “Univariate Analysis” lesson free?

Yes — the full text of “Univariate Analysis” is free to read here on the web, and the Pandas & NumPy Academy course includes 4 lessons in total. To practise it interactively (a built-in code editor and a 24/7 AI tutor) and unlock the rest of the Pandas & NumPy Academy course, upgrade to CoddyKit PRO.

What will I learn in “Univariate Analysis”?

Analyse each column independently: plot distributions for numerics and value counts for categoricals, note outliers and skewness. You practise Pandas & NumPy Academy with hands-on code you run directly in the browser, and a 24/7 AI tutor answers your questions as you work through the lesson.

Do I need any experience to start Pandas & NumPy Academy?

No prior experience is required. Pandas & NumPy Academy on CoddyKit is structured for beginners through advanced learners; this is — lesson 2 of 4, so you can start here or from the beginning and move at your own pace.

How long does the “Univariate Analysis” lesson take?

Most CoddyKit lessons take about 5–10 minutes. Each one is bite-sized and interactive, so you make steady progress and pick up exactly where you left off across the web and the app.

Can I write and run code in this Pandas & NumPy Academy lesson?

Yes. Every Pandas & NumPy Academy lesson includes a built-in code editor, so you write and run real code right in your browser and get instant AI feedback — no local setup required.

All lessons in this course

  1. Dataset Profiling Checklist
  2. Univariate Analysis
  3. Bivariate and Correlation Analysis
  4. Summarising Findings in a Report
← Back to Pandas & NumPy Academy