Turning Data Into Decisions
Bar charts, histograms, scatter plots, subplots, and plotting straight from pandas
Previously learned to draw a line — literally. we now know how to create a figure, style it, and save it. But real analyst work rarely stops at trends over time. You'll need to compare categories, understand distributions, spot relationships between variables, and show several views of the data at once. That's exactly what today covers.
Grab a coffee — let's turn raw numbers into charts that actually tell a story.
1. Bar Charts: Comparing Categories
When to use one
Bar charts are your go-to whenever you're comparing discrete categories against each other — regions, products, departments, months. If someone asks "which one is bigger?", a bar chart answers it instantly.
The code
import matplotlib.pyplot as plt
regions = ["North", "South", "East", "West"]
revenue = [420, 380, 510, 290]
fig, ax = plt.subplots(figsize=(7, 5))
ax.bar(regions, revenue, color="teal")
ax.set_title("Revenue by Region")
ax.set_xlabel("Region")
ax.set_ylabel("Revenue ($K)")
plt.show()
A useful variant: horizontal bars
When category names are long, flip the chart with barh() — it's far easier to read than squeezing labels sideways:
fig, ax = plt.subplots(figsize=(7, 5))
ax.barh(regions, revenue, color="darkorange")
ax.set_title("Revenue by Region")
ax.set_xlabel("Revenue ($K)")
plt.show()
Rule of thumb: categories on the x-axis → bar(). Long labels or many categories → barh().
2. Histograms: Understanding Distributions
Bar chart vs. histogram — don't mix them up
This trips up almost every beginner: a bar chart compares separate categories. A histogram shows how continuous numeric data is distributed by grouping values into ranges called bins. There are no gaps between histogram bars by convention, because the x-axis is continuous, not categorical.
The code
import matplotlib.pyplot as plt
ages = [22, 25, 25, 28, 30, 31, 31, 31, 35, 36, 38, 40, 42, 45, 45, 48, 50, 52, 55, 60]
fig, ax = plt.subplots(figsize=(7, 5))
ax.hist(ages, bins=6, color="steelblue", edgecolor="black")
ax.set_title("Customer Age Distribution")
ax.set_xlabel("Age")
ax.set_ylabel("Number of Customers")
plt.show()
Why bins matters
Too few bins hides detail; too many creates noise. bins=6 groups your 20 data points into 6 age ranges. Try changing it to bins=3 and bins=15 and watch the story the chart tells actually change — this is a great instinct to build early.
Use case: salary bands, order sizes, response times, test scores — anywhere you want to see the shape of the data (skewed? normal? clustered?).
3. Scatter Plots: Spotting Relationships
When to use one
Scatter plots answer "does X affect Y?" — like advertising spend vs. sales, or hours studied vs. exam score. Each point is one observation with two numeric values.
The code
import matplotlib.pyplot as plt
ad_spend = [10, 15, 20, 25, 30, 35, 40, 45]
sales = [22, 25, 33, 38, 44, 50, 58, 63]
fig, ax = plt.subplots(figsize=(7, 5))
ax.scatter(ad_spend, sales, color="crimson")
ax.set_title("Ad Spend vs Sales")
ax.set_xlabel("Ad Spend ($K)")
ax.set_ylabel("Sales ($K)")
plt.show()
Bonus: a third dimension with size or color
Scatter plots can secretly show a third variable by varying marker size (s=) or color (c=):
customer_count = [5, 8, 12, 15, 18, 22, 27, 30]
fig, ax = plt.subplots(figsize=(7, 5))
scatter = ax.scatter(ad_spend, sales, s=[c*10 for c in customer_count],
c=customer_count, cmap="viridis")
ax.set_title("Ad Spend vs Sales (bubble size = customers)")
ax.set_xlabel("Ad Spend ($K)")
ax.set_ylabel("Sales ($K)")
plt.colorbar(scatter, label="Customer Count")
plt.show()
This is called a bubble chart — a nice trick to have once you're comfortable with the basics.
4. Subplots: Multiple Charts, One Figure
Why you need this
Reports rarely show just one chart. Subplots let you lay out several plots in a grid inside a single figure — perfect for dashboards or side-by-side comparisons.
The code
import matplotlib.pyplot as plt
fig, axes = plt.subplots(1, 2, figsize=(12, 5)) # 1 row, 2 columns
# Left chart
axes[0].bar(regions, revenue, color="teal")
axes[0].set_title("Revenue by Region")
# Right chart
axes[1].hist(ages, bins=6, color="steelblue", edgecolor="black")
axes[1].set_title("Customer Age Distribution")
plt.tight_layout()
plt.show()
The pattern to remember
plt.subplots(rows, cols) gives you back an array of axes — axes[0], axes[1], etc. (or axes[0][0], axes[0][1]... for a 2D grid). Each one behaves exactly like the single ax you've been using — just call .bar(), .hist(), .scatter() on whichever one you want.
plt.tight_layout() is a small habit worth building now — it auto-adjusts spacing so titles and labels don't overlap.
5. Plotting Directly from a Pandas DataFrame
The analyst's real workflow
In practice, you're rarely typing out lists by hand — your data lives in a DataFrame. Pandas has a built-in .plot() method that calls Matplotlib for you, so you can skip a lot of boilerplate.
The code
import pandas as pd
import matplotlib.pyplot as plt
data = {
"Month": ["Jan", "Feb", "Mar", "Apr", "May"],
"Revenue": [45, 50, 47, 53, 60],
"Expenses": [30, 32, 31, 35, 38]
}
df = pd.DataFrame(data)
# Quick line plot straight from the DataFrame
df.plot(x="Month", y=["Revenue", "Expenses"], kind="line",
figsize=(8, 5), title="Revenue vs Expenses")
plt.ylabel("Amount ($K)")
plt.show()
Other kind values worth knowing
df.plot(x="Month", y="Revenue", kind="bar", figsize=(8, 5), color="seagreen")
plt.show()
kind accepts "line", "bar", "barh", "hist", "scatter", and more — one method, most of the charts you already learned today.
Key insight: df.plot() still returns a Matplotlib Axes object under the hood, which is why plt.ylabel(), plt.title(), etc. still work on it afterward. Everything you learned on Day 1 still applies.
6. Hands-On: From CSV to Chart
Here's a realistic mini-workflow — read tabular data and produce a combo chart:
import pandas as pd
import matplotlib.pyplot as plt
# In real use: df = pd.read_csv("sales_data.csv")
# Simulating that CSV here for practice:
data = {
"Month": ["Jan", "Feb", "Mar", "Apr", "May", "Jun"],
"Units_Sold": [120, 135, 128, 150, 170, 165],
"Revenue": [45, 50, 47, 53, 60, 58]
}
df = pd.DataFrame(data)
fig, ax1 = plt.subplots(figsize=(9, 5))
# Bar chart: units sold
ax1.bar(df["Month"], df["Units_Sold"], color="lightsteelblue", label="Units Sold")
ax1.set_xlabel("Month")
ax1.set_ylabel("Units Sold")
# Line chart: revenue, on a second y-axis
ax2 = ax1.twinx()
ax2.plot(df["Month"], df["Revenue"], color="darkred", marker="o", label="Revenue ($K)")
ax2.set_ylabel("Revenue ($K)")
fig.suptitle("Units Sold vs Revenue")
plt.savefig("units_vs_revenue.png", dpi=300, bbox_inches="tight")
plt.show()
ax1.twinx() is the trick here — it creates a second y-axis sharing the same x-axis, so you can combine a bar chart and line chart with different scales in one clean visual. This is a genuinely common real-world pattern (think "volume vs. price" charts).
Wrapping Up
In we've gone from a single line plot to:
- Comparing categories with bar charts
- Understanding data spread with histograms
- Spotting relationships with scatter plots
- Building dashboards with subplots
- Working the way real analysts do, straight from a pandas DataFrame
Where to go from here
Matplotlib is the foundation — but once it feels natural, two libraries are worth exploring next:
- Seaborn — built on Matplotlib, gives you polished statistical charts (correlation heatmaps, box plots) with less code
- Plotly — for interactive, hover-able charts, especially useful for dashboards and presentations
But don't rush there. Everything in Seaborn and Plotly still assumes you understand the figure/axes fundamentals you now have. That foundation is the real win from these two days.
This article was originally published by DEV Community and written by balaji s.
Read original article on DEV Community