Matplotlib Bar Chart: Complete Guide to plt.bar() and plt.barh()
Updated on
Bar charts are the most common way to compare quantities across categories. Revenue by quarter, scores by student, counts by status -- bar charts make these comparisons instantly readable. But creating effective bar charts in Matplotlib requires more than a basic plt.bar() call. You need to handle grouped comparisons, stacked compositions, horizontal layouts for long labels, and proper annotations that make charts self-explanatory.
This guide covers every bar chart pattern you'll need in Matplotlib, from basic vertical bars to advanced grouped and stacked configurations.
Basic Vertical Bar Chart
import matplotlib.pyplot as plt
categories = ['Python', 'JavaScript', 'Java', 'C++', 'Go']
values = [35, 28, 22, 15, 12]
plt.figure(figsize=(8, 5))
plt.bar(categories, values, color='steelblue', edgecolor='black', linewidth=0.5)
plt.xlabel('Language')
plt.ylabel('Popularity Score')
plt.title('Programming Language Popularity')
plt.show()Horizontal Bar Chart with plt.barh()
Use horizontal bars when category labels are long or when you have many categories:
import matplotlib.pyplot as plt
frameworks = ['React', 'Vue.js', 'Angular', 'Svelte', 'Next.js',
'Django', 'Flask', 'FastAPI', 'Express', 'Rails']
stars = [220, 207, 95, 78, 124, 78, 67, 74, 64, 55]
plt.figure(figsize=(10, 6))
plt.barh(frameworks, stars, color='#3498db', edgecolor='white')
plt.xlabel('GitHub Stars (thousands)')
plt.title('Framework Popularity by GitHub Stars')
plt.gca().invert_yaxis() # Highest at top
plt.tight_layout()
plt.show()Customizing Colors
import matplotlib.pyplot as plt
categories = ['Q1', 'Q2', 'Q3', 'Q4']
revenue = [120, 150, 180, 200]
# Different color per bar
colors = ['#e74c3c', '#f39c12', '#2ecc71', '#3498db']
plt.figure(figsize=(8, 5))
bars = plt.bar(categories, revenue, color=colors, edgecolor='black', linewidth=0.5)
plt.ylabel('Revenue ($K)')
plt.title('Quarterly Revenue')
plt.show()Adding Value Labels on Bars
import matplotlib.pyplot as plt
categories = ['A', 'B', 'C', 'D', 'E']
values = [23, 45, 56, 78, 32]
plt.figure(figsize=(8, 5))
bars = plt.bar(categories, values, color='steelblue')
# Add value labels on top of each bar
for bar, val in zip(bars, values):
plt.text(bar.get_x() + bar.get_width() / 2, bar.get_height() + 1,
str(val), ha='center', va='bottom', fontsize=11)
plt.ylabel('Value')
plt.title('Bar Chart with Value Labels')
plt.show()Grouped Bar Chart
Compare multiple series side by side:
import matplotlib.pyplot as plt
import numpy as np
categories = ['Q1', 'Q2', 'Q3', 'Q4']
product_a = [20, 35, 30, 35]
product_b = [25, 32, 34, 20]
product_c = [15, 20, 25, 30]
x = np.arange(len(categories))
width = 0.25
plt.figure(figsize=(10, 6))
plt.bar(x - width, product_a, width, label='Product A', color='#e74c3c')
plt.bar(x, product_b, width, label='Product B', color='#3498db')
plt.bar(x + width, product_c, width, label='Product C', color='#2ecc71')
plt.xlabel('Quarter')
plt.ylabel('Sales ($K)')
plt.title('Quarterly Sales by Product')
plt.xticks(x, categories)
plt.legend()
plt.tight_layout()
plt.show()Stacked Bar Chart
Show composition of each category:
import matplotlib.pyplot as plt
quarters = ['Q1', 'Q2', 'Q3', 'Q4']
mobile = [30, 35, 40, 45]
desktop = [50, 45, 35, 30]
tablet = [20, 20, 25, 25]
plt.figure(figsize=(8, 6))
plt.bar(quarters, mobile, label='Mobile', color='#3498db')
plt.bar(quarters, desktop, bottom=mobile, label='Desktop', color='#e74c3c')
# For third stack, calculate cumulative bottom
import numpy as np
bottom_2 = np.array(mobile) + np.array(desktop)
plt.bar(quarters, tablet, bottom=bottom_2, label='Tablet', color='#2ecc71')
plt.ylabel('Traffic (%)')
plt.title('Traffic Sources by Quarter')
plt.legend()
plt.show()Error Bars
import matplotlib.pyplot as plt
import numpy as np
categories = ['Control', 'Treatment A', 'Treatment B', 'Treatment C']
means = [10.2, 15.8, 14.3, 18.1]
errors = [1.2, 2.1, 1.8, 2.5]
plt.figure(figsize=(8, 5))
plt.bar(categories, means, yerr=errors, capsize=5,
color='steelblue', edgecolor='black', linewidth=0.5)
plt.ylabel('Response Value')
plt.title('Treatment Effects with Error Bars')
plt.show()plt.bar() Parameter Reference
| Parameter | Type | Description |
|---|---|---|
x | array-like | Bar positions (categories) |
height | array-like | Bar heights (values) |
width | float | Bar width (default 0.8) |
bottom | array-like | Y-coordinate of bar bases (for stacking) |
color | color or array | Bar face color(s) |
edgecolor | color | Bar edge color |
linewidth | float | Edge line width |
yerr / xerr | array-like | Error bar sizes |
capsize | float | Error bar cap width |
align | str | Bar alignment ('center' or 'edge') |
label | str | Legend label |
alpha | float | Transparency (0-1) |
Interactive Bar Charts with PyGWalker
For exploratory data analysis, PyGWalker (opens in a new tab) lets you create interactive bar charts by dragging and dropping columns from your DataFrame inside Jupyter:
import pandas as pd
import pygwalker as pyg
df = pd.DataFrame({
'Quarter': ['Q1', 'Q2', 'Q3', 'Q4'] * 3,
'Product': ['A'] * 4 + ['B'] * 4 + ['C'] * 4,
'Sales': [20, 35, 30, 35, 25, 32, 34, 20, 15, 20, 25, 30]
})
walker = pyg.walk(df)FAQ
How do I create a bar chart in Matplotlib?
Use plt.bar(categories, values) for vertical bars or plt.barh(categories, values) for horizontal bars. Pass lists or arrays for categories and their corresponding values. Add plt.xlabel(), plt.ylabel(), and plt.title() for labels.
How do I create a grouped bar chart?
Use np.arange() for x positions and offset each group by the bar width. Call plt.bar() multiple times with shifted x positions: plt.bar(x - width, data1, width), plt.bar(x, data2, width), etc. Set tick labels with plt.xticks(x, categories).
How do I add value labels on top of bars?
Loop over the bar objects and use plt.text(). For each bar, calculate the center x position with bar.get_x() + bar.get_width() / 2 and the y position with bar.get_height(). Use ha='center' for horizontal alignment.
How do I create a stacked bar chart?
Use the bottom parameter in successive plt.bar() calls. The first call has no bottom. The second call uses the first dataset as bottom. For a third stack, sum the first two datasets as bottom.
When should I use horizontal vs vertical bar charts?
Use horizontal bars (plt.barh()) when category labels are long, when you have many categories (more than 8-10), or when comparing to a baseline. Use vertical bars (plt.bar()) for time series categories (months, quarters) or when you have few categories with short labels.
Conclusion
Matplotlib's plt.bar() and plt.barh() cover every bar chart need: basic comparisons, grouped multi-series, stacked compositions, and annotated presentations. For grouped bars, offset x positions with np.arange(). For stacked bars, use the bottom parameter. Always add value labels for clarity and choose horizontal layout when labels are long.