Skip to content

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

ParameterTypeDescription
xarray-likeBar positions (categories)
heightarray-likeBar heights (values)
widthfloatBar width (default 0.8)
bottomarray-likeY-coordinate of bar bases (for stacking)
colorcolor or arrayBar face color(s)
edgecolorcolorBar edge color
linewidthfloatEdge line width
yerr / xerrarray-likeError bar sizes
capsizefloatError bar cap width
alignstrBar alignment ('center' or 'edge')
labelstrLegend label
alphafloatTransparency (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.

📚