How to Create a Bar Chart in Python: matplotlib, seaborn, and plotly

The query "how to create a bar chart in Python" sounds simple, but publication-ready bar charts need more than one line of code. In scientific work, you often need grouped comparisons, uncertainty bars, and clear axis labeling that survives peer review.
Category comparison
Bar charts are best when each bar represents a distinct category and all bars share a zero baseline.
Grouped designs
Grouped bars are useful when each category has two or more conditions to compare side by side.
Uncertainty first
In manuscripts, bars without SD, SEM, or confidence intervals are usually incomplete evidence.
1. Basic matplotlib bar chart
Start with plain matplotlib for full control. Use a y-axis starting at zero and annotate bar values for fast reading.
import matplotlib.pyplot as plt
categories = ["Control", "Treatment A", "Treatment B", "Treatment C"]
values = [62.4, 71.2, 79.8, 68.9]
fig, ax = plt.subplots(figsize=(8, 5))
ax.bar(categories, values, color=["#4f46e5", "#0891b2", "#16a34a", "#d97706"])
ax.set_ylabel("Response score")
ax.set_xlabel("Condition")
ax.set_title("Mean response by condition")
ax.set_ylim(0, 90)
ax.grid(axis="y", alpha=0.25)
for i, value in enumerate(values):
ax.text(i, value + 1.2, f"{value:.1f}", ha="center", fontsize=10)
plt.tight_layout()2. Grouped bar chart in matplotlib
Grouped bars are the standard for treatment-vs-control across time points or assay conditions. Offset x positions using width/2.
import numpy as np
import matplotlib.pyplot as plt
conditions = ["Week 1", "Week 2", "Week 3", "Week 4"]
control = [55, 57, 60, 62]
treatment = [56, 62, 69, 74]
x = np.arange(len(conditions))
width = 0.38
fig, ax = plt.subplots(figsize=(9, 5))
ax.bar(x - width / 2, control, width, label="Control", color="#64748b")
ax.bar(x + width / 2, treatment, width, label="Treatment", color="#10b981")
ax.set_xticks(x)
ax.set_xticklabels(conditions)
ax.set_ylabel("Cell viability (%)")
ax.set_title("Grouped bar chart across time")
ax.legend(frameon=False)
ax.grid(axis="y", alpha=0.25)
plt.tight_layout()3. Bar chart with error bars
Try it
Try it now: compare your groups with the right chart
Generate box, violin, or bar charts directly from your dataset and choose the clearest visual for your paper.
Generate comparison charts →Newsletter
Get a weekly Python plotting tip
One concise tip each week for cleaner, faster scientific figures. Built for researchers who publish.
For scientific plots, pass yerr and capsize. Then state in your caption whether bars represent SD, SEM, or 95% CI.
import numpy as np
import matplotlib.pyplot as plt
groups = ["Control", "Drug A", "Drug B", "Drug C"]
means = np.array([1.00, 1.22, 1.41, 1.18])
sem = np.array([0.06, 0.07, 0.09, 0.05])
fig, ax = plt.subplots(figsize=(8, 5))
ax.bar(groups, means, yerr=sem, capsize=5, color="#0f172a", alpha=0.88)
ax.set_ylabel("Normalized expression")
ax.set_title("Bar chart with SEM error bars")
ax.set_ylim(0, 1.65)
ax.grid(axis="y", alpha=0.25)
for i, mean in enumerate(means):
ax.text(i, mean + sem[i] + 0.03, f"{mean:.2f}", ha="center", fontsize=10)
plt.tight_layout()4. Seaborn vs plotly vs matplotlib
Use matplotlib when you need low-level layout control, seaborn when you want fast statistical defaults, and plotly when interactivity matters.
Seaborn quick start
import seaborn as sns
import matplotlib.pyplot as plt
# df columns: condition, value
sns.set_theme(style="whitegrid")
ax = sns.barplot(data=df, x="condition", y="value", errorbar=("ci", 95), palette="crest")
ax.set_title("Seaborn barplot with 95% CI")
ax.set_xlabel("Condition")
ax.set_ylabel("Signal intensity")
plt.tight_layout()Plotly quick start
import plotly.express as px
# df columns: condition, value, sem
fig = px.bar(
df,
x="condition",
y="value",
error_y="sem",
color="condition",
title="Interactive bar chart with error bars",
)
fig.update_layout(template="plotly_white", showlegend=False)
fig.show()Common bar chart mistakes
- Non-zero baseline - truncating y-axis can exaggerate small differences.
- Missing uncertainty - no error bars makes interpretation weak for reviewer scrutiny.
- Too many categories - for long labels or 15+ groups, use horizontal bars or a dot plot.
- Rainbow palette overload - use restrained, purposeful colors tied to conditions.
Need an editable bar chart now? Open the bar chart gallery page for prompt templates, then run the workflow in the analyze tool.
Related chart guides
Apply this tutorial directly in the chart gallery with ready-to-run prompts and examples.
Technique guides scientists read next
scipy.signal.find_peaks guide
Tune prominence and width parameters for robust peak extraction.
Savitzky-Golay smoothing
Reduce noise while preserving peak shape and position.
PCA visualization workflow
Move from high-dimensional measurements to interpretable components.
ANOVA with post-hoc brackets
Add statistically correct pairwise significance annotations.
Found this helpful? Share it with your network.
Experimental Physicist & Photonics Researcher
Hands-on experience in silicon photonics, semiconductor fabrication (DRIE/ICP-RIE), optical simulation, and data-driven analysis. Built Plotivy to help researchers focus on discoveries instead of data struggles.
More about the authorVisualize your own data
Apply the techniques from this article to your own datasets. Upload CSV, Excel, or paste data directly.