How to Create Bar Charts with ggplot2 in R
Bar charts display counts across categories. The key distinction in ggplot2 is between geom_bar(), which counts observations automatically, and geom_col(), which uses an existing count or summary column. When you create bar charts with these two geometries, nearly every categorical plotting need is covered.
library(ggplot2)
# geom_bar() counts rows for you
ggplot(mpg, aes(x = class)) +
geom_bar()
# geom_col() uses a pre-computed value column
cars <- data.frame(
model = c("Sedan", "SUV", "Truck", "Coupe"),
sales = c(120, 95, 60, 45)
)
ggplot(cars, aes(x = model, y = sales)) +
geom_col()
Add fill to color bars by a grouping variable: geom_bar(aes(fill = drv)) stacks subgroups, while geom_bar(aes(fill = drv), position = "dodge") places them side by side. Flip bars horizontal with coord_flip(). To reorder bars by value instead of alphabetically, use forcats::fct_reorder(category, -count). For proportional stacked bars showing percentages instead of counts, set position = "fill" and add scale_y_continuous(labels = scales::percent). When you have pre-computed summary data, always prefer geom_col() over geom_bar(stat = "identity") — it communicates intent more clearly. To add value labels on top of each bar, pair geom_text(aes(label = sales), vjust = -0.5) with geom_col() and adjust vertical justification as needed. The width argument in geom_bar() and geom_col() tightens or widens bars relative to the default spacing. For horizontal bar charts, swap coord_flip() for setting the x aesthetic to the count variable instead.
# Stacked bars colored by drive type
ggplot(mpg, aes(x = class, fill = drv)) +
geom_bar()
# Side-by-side bars
ggplot(mpg, aes(x = class, fill = drv)) +
geom_bar(position = "dodge")
See also
- Introduction to ggplot2, Getting started
- Customizing ggplot2 Charts, Styling and themes