Plotting with Pandas
Draw quick charts straight from a DataFrame or Series with .plot(kind=...) — line, bar, barh, hist, box, kde, area, pie, scatter and hexbin — and know which chart answers which question.
The course notebooks end almost every analysis with a chart: ipl3['year'].value_counts().sort_index().plot(kind='bar'), df['Brand Name'].value_counts().head().plot(kind='pie'). A table of 10 numbers is hard to read; a bar chart of the same numbers is understood in one second. Pandas wraps Matplotlib so that any Series or DataFrame can draw itself with .plot().
Note: charts can't be shown in this site's text playground, so the examples on this page are marked not runnable. Run them in Jupyter Notebook / Google Colab, where the chart appears below the cell (add
plt.show()in a plain.pyscript).
Definition
DataFrame.plot()/Series.plot()is pandas' built-in plotting method. It draws a Matplotlib chart from the data — the index becomes the x-axis and each numeric column becomes a series (line, bar, …) — and returns the Matplotlib Axes object so you can customise it further.
- Built on Matplotlib — you need
matplotlibinstalled; pandas just calls it for you. - Index → x-axis — this is why
value_counts()andgroupby(...).sum()results plot so nicely: their index is the category. - Each column → one series — a DataFrame with 3 numeric columns draws 3 lines (or 3 bars per group).
- Returns Axes — you can call
ax.set_title(...),ax.set_ylabel(...)on it.
Syntax
python
import matplotlib.pyplot as plt
df.plot(kind="line", x=None, y=None, title=None, figsize=None,
legend=True, grid=False, color=None, rot=None, subplots=False)
df.plot.bar(...) # same as df.plot(kind="bar", ...)
plt.show() # needed in scripts; optional in Jupyter| Parameter | Meaning | Default |
|---|---|---|
kind | chart type: "line", "bar", "barh", "hist", "box", "kde"/"density", "area", "pie", "scatter", "hexbin" | "line" |
x, y | columns for the axes (DataFrame only; scatter/hexbin need both) | index / all numeric columns |
title | chart title | None |
figsize | (width, height) in inches | Matplotlib default |
legend | show the legend | True |
color | one colour or a list of colours | automatic |
rot | rotate x tick labels (degrees) | depends on kind |
subplots | one small chart per column | False |
bins (hist) | number of bars in a histogram | 10 |
autopct (pie) | label format, e.g. "%.1f%%" | None |
Chart kinds — what each shows and when to use it
kind | What it shows | Use it when… | Cricket example |
|---|---|---|---|
line | values connected in order | the x-axis is time or ordered | matches per season |
bar | one vertical bar per category | comparing a few categories | wins per team |
barh | horizontal bars | long category names or many categories | top 10 venues |
hist | how values are distributed (counts in ranges) | understanding one numeric column | spread of first-innings scores |
box | median, quartiles, outliers | comparing spread, spotting outliers | runs per match by team |
kde / density | smooth curve of the distribution | a cleaner version of a histogram | strike-rate distribution |
area | stacked filled lines | parts of a total over time | runs from 4s vs 6s per season |
pie | slices of a whole | few parts (≤ 5) of 100% | toss decision: bat vs field |
scatter | one dot per row, x vs y | relationship between two numbers | horsepower vs price |
hexbin | scatter for many points, density by colour | thousands of overlapping points | balls faced vs runs (all innings) |
Example — bar chart of wins per team
python
import pandas as pd
import matplotlib.pyplot as plt
wins = pd.Series({"CSK": 5, "MI": 5, "KKR": 3, "RCB": 2, "SRH": 2, "DC": 1})
ax = wins.plot(kind="bar", title="Wins per team", color="steelblue", rot=0)
ax.set_xlabel("Team")
ax.set_ylabel("Wins")
plt.show()What you see: six vertical bars, team codes along the x-axis (the Series index), bar height = wins. CSK and MI are the tallest. rot=0 keeps labels horizontal. Bar charts are the default choice for "compare categories".
Example — line chart over seasons
python
season_runs = pd.DataFrame(
{"MI": [2380, 2410, 2650], "CSK": [2520, 2300, 2150]},
index=[2018, 2019, 2020],
)
season_runs.plot(kind="line", marker="o", title="Total runs per season")
plt.show()What you see: two lines (one per column) across 2018–2020, with a legend for MI and CSK. Use a line chart only when the x-axis has a natural order — never for unordered categories like team names.
Example — histogram and box plot for distributions
python
import numpy as np
rng = np.random.default_rng(42)
scores = pd.DataFrame({
"MI": rng.normal(170, 20, 50).round(),
"CSK": rng.normal(165, 12, 50).round(),
})
scores.plot(kind="hist", bins=15, alpha=0.6, title="First-innings totals")
scores.plot(kind="box", title="First-innings totals by team")
plt.show()What you see: the histogram shows two overlapping "hills" — where scores are most common and how wide they spread (alpha=0.6 makes them see-through). The box plot shows each team's median (middle line), the middle 50% (the box), the whiskers, and dots for outliers. MI's taller box means its scores vary more.
Example — scatter for relationships, pie for parts of a whole
python
cars = pd.DataFrame({"horsepower": [89, 103, 114, 148, 201, 182, 130],
"price": [6.5, 9.5, 13.5, 19.5, 33.0, 21.0, 15.5]})
cars.plot(kind="scatter", x="horsepower", y="price", title="Horsepower vs price")
toss = pd.Series({"field": 15, "bat": 3})
toss.plot(kind="pie", autopct="%.1f%%", title="Toss decisions", ylabel="")
plt.show()What you see: the scatter shows dots rising from bottom-left to top-right — the visual form of the strong positive correlation (0.95) found in the car project. The pie shows 83.3% field vs 16.7% bat. Use pies only for a handful of slices; with many categories a bar chart is easier to compare.
Typical notebook patterns
python
df["city"].value_counts().head(10).plot(kind="barh") # top 10 categories
df["year"].value_counts().sort_index().plot(kind="bar") # counts per year, in year order
df.groupby("brand")["price"].mean().sort_values().plot(kind="bar") # average per group
df[["runs", "balls"]].plot(subplots=True, figsize=(8, 6)) # one chart per columnCommon mistakes
- ❌ Plotting
value_counts()of years without.sort_index()— bars appear in count order, not year order. ✅.value_counts().sort_index().plot(...). - ❌ A line chart for unordered categories (teams). ✅ Use
bar/barh. - ❌ A pie chart with 15 slices. ✅ Pies for ≤ 5 parts; otherwise
barh. - ❌
kind="scatter"withoutxandy. ✅ Scatter and hexbin need both column names. - ❌ Nothing appears in a
.pyscript. ✅ Callplt.show()(Jupyter shows charts automatically). - ❌ Plotting a text column — "no numeric data to plot". ✅ Plot counts (
value_counts()) or numeric columns.
Interview tip
Q: Which chart would you use to check whether a numeric column has outliers?
A: A box plot (df["col"].plot(kind="box")) — points beyond the whiskers (1.5 × IQR from the box) are drawn individually as outliers. A histogram is the companion chart for seeing the overall shape of the distribution.
Key points to remember
- Series.plot / DataFrame.plot draw Matplotlib charts; the index becomes the x-axis and each numeric column a series.
- kind= chooses the chart: line, bar, barh, hist, box, kde, area, pie, scatter, hexbin (or use df.plot.bar(...)).
- Bar/barh compare categories; line shows change over ordered x (time); hist/kde/box show distributions.
- Scatter (and hexbin for many points) shows the relationship between two numeric columns — needs x and y.
- Pie charts only for a few parts of a whole; otherwise use barh.
- Common pattern: value_counts() / groupby().mean() → sort → .plot(kind='bar').
- In a .py script call plt.show(); in Jupyter charts appear automatically.
Try it yourself
Bar and line charts (run in Jupyter/Colab)
import pandas as pd
import matplotlib.pyplot as plt
wins = pd.Series({"CSK": 5, "MI": 5, "KKR": 3, "RCB": 2, "SRH": 2, "DC": 1})
ax = wins.plot(kind="bar", title="Wins per team", color="steelblue", rot=0)
ax.set_xlabel("Team")
ax.set_ylabel("Wins")
plt.show()
season_runs = pd.DataFrame(
{"MI": [2380, 2410, 2650], "CSK": [2520, 2300, 2150]},
index=[2018, 2019, 2020],
)
season_runs.plot(kind="line", marker="o", title="Total runs per season")
plt.show()Not runnable in the in-browser playground — try it locally.
Distributions: hist and box (run in Jupyter/Colab)
import pandas as pd
import numpy as np
import matplotlib.pyplot as plt
rng = np.random.default_rng(42)
scores = pd.DataFrame({
"MI": rng.normal(170, 20, 50).round(),
"CSK": rng.normal(165, 12, 50).round(),
})
scores.plot(kind="hist", bins=15, alpha=0.6, title="First-innings totals")
scores.plot(kind="box", title="First-innings totals by team")
plt.show()Not runnable in the in-browser playground — try it locally.
Scatter and pie (run in Jupyter/Colab)
import pandas as pd
import matplotlib.pyplot as plt
cars = pd.DataFrame({"horsepower": [89, 103, 114, 148, 201, 182, 130],
"price": [6.5, 9.5, 13.5, 19.5, 33.0, 21.0, 15.5]})
cars.plot(kind="scatter", x="horsepower", y="price", title="Horsepower vs price")
toss = pd.Series({"field": 15, "bat": 3})
toss.plot(kind="pie", autopct="%.1f%%", title="Toss decisions", ylabel="")
plt.show()Not runnable in the in-browser playground — try it locally.
Revision Flashcards
Tap a card to flip it and see the answer.
