Free tutorials & notes in Hindi & English · Clean code examples 🧰 Free PDF & Image Tools →
🧹 Week 3 – Data Cleaning & EDA  ·  Day 18

Day 18: Exploratory Data Analysis (EDA)

⏱ 2.5 hours📶 Intermediate🎯 100% self-study
Day 18 / 60

✅ Today you will learn

  • The 6-step EDA framework
  • Univariate: histograms, value counts, skew
  • Outliers with the IQR rule and box plots
  • Bivariate: numeric vs target, category vs target
  • Correlation heatmap and turning charts into insights

🏢 In the real world

A property start-up gives you 800 house listings from six cities and asks one question: “What drives price?” Before any machine learning, EDA tells you which features matter, which values are suspicious and what story the data tells.

The EDA framework

  1. 1Understand: shape, columns, types
  2. 2Quality: missing, duplicates
  3. 3Univariate: one column at a time
  4. 4Outliers
  5. 5Bivariate: each feature vs target
  6. 6Summarise insights
Use this on every new dataset

Steps 1–2: understand and check quality

Python
import pandas as pd
h = pd.read_csv("house_prices.csv")
print(h.shape)
print(h.head(3))
print("Missing:", h.isna().sum().sum(), "| duplicates:", h.duplicated().sum())
print(h.describe().round(1).T[["mean", "50%", "min", "max"]])
(800, 9) city area_sqft bedrooms bathrooms age_years metro_km furnishing parking price_lakh 0 Pune 1210 2 2 18 7.0 Furnished No 55.07 1 Bengaluru 850 2 2 15 4.6 Semi-Furnished No 48.22 2 Hyderabad 530 1 1 8 2.1 Semi-Furnished Yes 26.64 Missing: 0 | duplicates: 0 mean 50% min max area_sqft 1150.7 1090.0 400.0 3080.0 bedrooms 2.4 2.0 1.0 5.0 bathrooms 2.0 2.0 1.0 5.0 age_years 12.7 13.0 0.0 25.0 metro_km 3.4 2.3 0.2 18.0 price_lakh 56.8 54.3 10.7 200.0

Step 3: univariate analysis

Python
import pandas as pd
import matplotlib.pyplot as plt
h = pd.read_csv("house_prices.csv")
fig, ax = plt.subplots(1, 3, figsize=(12, 3.6))
ax[0].hist(h["price_lakh"], bins=30, color="#4f46e5"); ax[0].set_title("Price (₹ lakh)")
ax[1].hist(h["area_sqft"], bins=30, color="#0891b2"); ax[1].set_title("Area (sqft)")
h["city"].value_counts().plot(kind="bar", ax=ax[2], color="#f59e0b"); ax[2].set_title("Listings per city")
ax[2].tick_params(axis="x", rotation=30)
plt.tight_layout(); plt.show()
print("Skew → price:", round(h["price_lakh"].skew(), 2), "| area:", round(h["area_sqft"].skew(), 2))
Skew → price: 1.06 | area: 1.06
Three panels: price histogram, area histogram, listings per city
Price is right-skewed: many mid-range homes and a long tail of expensive ones.
📐 Skewness in one line

Skew ≈ 0: symmetric. Skew > 1: long right tail (prices, incomes) – the mean is pulled above the median, so report the median and consider a log transform later.

Step 4: outliers with IQR

Python
import pandas as pd
h = pd.read_csv("house_prices.csv")
q1, q3 = h["price_lakh"].quantile([0.25, 0.75])
iqr = q3 - q1
low, high = q1 - 1.5 * iqr, q3 + 1.5 * iqr
out = h[(h["price_lakh"] < low) | (h["price_lakh"] > high)]
print(f"Q1={q1:.1f} Q3={q3:.1f} IQR={iqr:.1f} → normal range {low:.1f} to {high:.1f} lakh")
print(len(out), "outliers")
print(out.sort_values("price_lakh", ascending=False)[["city", "area_sqft", "bedrooms", "price_lakh"]].head())
Q1=39.1 Q3=69.7 IQR=30.7 → normal range -6.9 to 115.7 lakh 19 outliers city area_sqft bedrooms price_lakh 290 Hyderabad 3080 5 199.97 217 Bengaluru 2450 5 162.50 742 Pune 2790 5 158.92 56 Bengaluru 2740 5 145.01 352 Bengaluru 2650 5 144.53
Python
import pandas as pd
import seaborn as sns
import matplotlib.pyplot as plt
h = pd.read_csv("house_prices.csv")
order = h.groupby("city")["price_lakh"].median().sort_values().index
plt.figure(figsize=(9, 4))
sns.boxplot(data=h, x="city", y="price_lakh", order=order, color="#a5b4fc")
plt.title("Price by city – boxes show the middle 50%, dots are outliers")
plt.ylabel("₹ lakh"); plt.show()
Box plot of house prices for each city
The outliers are mostly large homes in expensive cities – real, not errors. Keep them.
💡 Outlier ≠ error

Remove values that are impossible (negative area). Investigate values that are rare but possible (a 3,000 sqft villa). Often you keep them – or cap them – rather than delete.

Step 5: bivariate analysis

Python
import pandas as pd
import matplotlib.pyplot as plt
h = pd.read_csv("house_prices.csv")
fig, ax = plt.subplots(1, 2, figsize=(11, 4))
ax[0].scatter(h["area_sqft"], h["price_lakh"], s=10, alpha=0.5, color="#4f46e5")
ax[0].set_xlabel("Area (sqft)"); ax[0].set_ylabel("Price (₹ lakh)"); ax[0].set_title("Bigger homes cost more")
h["ppsf"] = h["price_lakh"] * 1e5 / h["area_sqft"]               # price per sqft removes the size effect
band = pd.cut(h["metro_km"], [0, 1, 2, 4, 7, 18], labels=["<1", "1-2", "2-4", "4-7", "7+"])
h.groupby(band, observed=True)["ppsf"].median().plot(kind="bar", ax=ax[1], color="#dc2626", rot=0)
ax[1].set_xlabel("Distance to metro (km)"); ax[1].set_ylabel("₹ per sqft"); ax[1].set_title("Farther from metro → cheaper per sqft")
plt.tight_layout(); plt.show()
Scatter of area vs price and line of metro distance vs price
Area pushes price up; distance from the metro pulls it down.
Python
import pandas as pd
h = pd.read_csv("house_prices.csv")
for col in ["furnishing", "parking", "bedrooms"]:
    print(h.groupby(col)["price_lakh"].median().round(1).to_dict())
{'Furnished': 55.8, 'Semi-Furnished': 54.1, 'Unfurnished': 52.1} {'No': 50.6, 'Yes': 56.0} {1: 35.1, 2: 47.7, 3: 62.8, 4: 80.5, 5: 102.8}
Python
import pandas as pd
import seaborn as sns
import matplotlib.pyplot as plt
h = pd.read_csv("house_prices.csv")
corr = h.select_dtypes("number").corr().round(2)
print(corr["price_lakh"].sort_values(ascending=False))
plt.figure(figsize=(6.5, 5))
sns.heatmap(corr, annot=True, cmap="RdBu_r", vmin=-1, vmax=1, fmt=".2f")
plt.title("Correlation matrix"); plt.show()
price_lakh 1.00 area_sqft 0.83 bedrooms 0.68 bathrooms 0.61 age_years -0.15 metro_km -0.20 Name: price_lakh, dtype: float64
Correlation heatmap of numeric house features
Red = move together, blue = move opposite. Area, bedrooms and bathrooms are also correlated with each other.

Step 6: write insights, not just charts

📏
Area is #1Price rises steadily with area – strongest correlation.
🚇
Metro premiumHomes near the metro sell for clearly more.
🏙️
City mattersSame size, very different price in Bengaluru vs Lucknow.
🏚️
Age discountsOlder buildings are cheaper; furnishing adds a little.
EDA summary for the start-up
Python
import pandas as pd
def quick_eda(df, target):
    print("Shape:", df.shape, "| missing:", int(df.isna().sum().sum()), "| dups:", int(df.duplicated().sum()))
    num = df.select_dtypes("number").drop(columns=[target])
    print("Top numeric drivers:", num.corrwith(df[target]).abs().sort_values(ascending=False).round(2).head(3).to_dict())
    for c in df.select_dtypes("object").columns:
        g = df.groupby(c)[target].median()
        print(f"{c}: best={g.idxmax()} ({g.max():.1f}) worst={g.idxmin()} ({g.min():.1f})")
quick_eda(pd.read_csv("house_prices.csv"), "price_lakh")
Shape: (800, 9) | missing: 0 | dups: 0 Top numeric drivers: {'area_sqft': 0.83, 'bedrooms': 0.68, 'bathrooms': 0.61} city: best=Bengaluru (64.4) worst=Lucknow (36.1) furnishing: best=Furnished (55.8) worst=Unfurnished (52.1) parking: best=Yes (56.0) worst=No (50.6)

🏅 Job skills unlocked today

✔ Follow a repeatable EDA checklist✔ Detect outliers with IQR✔ Compare features against a target✔ Write business insights from charts

Practice tasks

🏋️ Practice – do it yourself

Task 1: Run quick_eda on students_performance.csv with target average.
Show solution
Python
import pandas as pd
def quick_eda(df, target):
    num = df.select_dtypes("number").drop(columns=[target, "maths", "science", "english"])
    print(num.corrwith(df[target]).round(2).sort_values(ascending=False).to_dict())
    for c in ["gender", "school_type", "tuition", "internet", "parent_education"]:
        print(c, df.groupby(c)[target].mean().round(1).to_dict())
quick_eda(pd.read_csv("students_performance.csv"), "average")
{'study_hours': 0.79, 'attendance': 0.39} gender {'Female': 65.9, 'Male': 66.6} school_type {'Government': 66.3, 'Private': 66.3} tuition {'No': 66.3, 'Yes': 66.3} internet {'No': 63.3, 'Yes': 67.1} parent_education {'Graduate': 68.1, 'Post-Graduate': 67.0, 'School': 63.3}
Task 2: Find outliers in monthly_charges of the telecom data with the IQR rule.
Show solution
Python
import pandas as pd
t = pd.read_csv("telecom_churn.csv")
q1, q3 = t["monthly_charges"].quantile([.25, .75]); i = q3 - q1
print(((t["monthly_charges"] < q1 - 1.5 * i) | (t["monthly_charges"] > q3 + 1.5 * i)).sum(), "outliers")
0 outliers
Task 3: Which numeric column is most correlated with spending_score in mall_customers.csv? Is the relationship linear? (Hint: scatter plot.)
Show solution
Python
import pandas as pd
m = pd.read_csv("mall_customers.csv")
print(m.select_dtypes("number").corr()["spending_score"].round(2))
print("Age is strongly negative; income looks weak overall, yet a scatter shows clear clusters (Day 46).")
age -0.64 annual_income_lakh 0.22 spending_score 1.00 Name: spending_score, dtype: float64 Age is strongly negative; income looks weak overall, yet a scatter shows clear clusters (Day 46).

Quick quiz

🧠 Quick Quiz – test yourself

1. The IQR rule flags values above…
And below Q1 − 1.5 × IQR.
2. A right-skewed column has…
The long right tail pulls the mean up.
3. Correlation of −0.6 between metro_km and price means…
Negative = opposite directions. Correlation is not causation.
4. Best chart to compare a numeric distribution across cities?
Box plots show median, spread and outliers side by side.
5. An outlier that is real but rare should usually be…
Deleting real data hides real customers.

Interview corner

💼 Interview Corner

Walk me through your EDA process.

Understand the business question and columns; check shape, types, missing values and duplicates; look at each variable (histograms, value_counts); detect outliers; relate each feature to the target (scatter, box, group medians, correlation); then write 3–5 insights and next steps for modelling.

Two features are highly correlated with each other. Is that a problem?

For prediction with tree models, usually not. For linear models it causes multicollinearity – unstable coefficients – so you may drop one, combine them or use regularisation (Day 39).

Summary

  • EDA = understand → quality → univariate → outliers → bivariate → insights.
  • Use median for skewed data; IQR to flag outliers.
  • Box plots for category vs number; scatter for number vs number; heatmap for correlations.
  • Always end with written insights.
➡️ Next

Day 19: Mini project – full EDA of BazaarKart’s 2024 sales with a management summary.

Frequently Asked Questions

Are there tools that do EDA automatically?
Yes – ydata-profiling and sweetviz create HTML reports. They are useful for a first look, but you still need to think and write insights yourself.
How long should EDA take?
In real projects often 30–50% of the time. It saves far more time later by preventing wrong models.
← Data Science (60 Days)
🔗

Share this topic with a friend

यह topic किसी दोस्त को भेजें

Found it useful? Send it to a classmate learning the same thing.

अच्छा लगा? जो दोस्त यही सीख रहा है, उसे भेज दीजिए।

Next topicDay 19: Mini Project: Retail Sales EDA Your progress: 18 / 60 (30%) · Lesson 19 / 60 Continue →

How was this lesson?

Your feedback helps us make the content better.

Write a review or suggestion (optional)

After approval, your name and city may appear publicly with your review. Please do not write your email or phone number.

▶ CodingEasily on YouTube

Learn with video lessons in easy Hindi

Featured video: RDBMS Part 3 – Class XI Commerce IT

▶ Subscribe – it’s free