ComparisonRanking CategoricalNumerical

Bar Chart

ggplot2: geom_col() / geom_bar() · Package: ggplot2 · Variables: 1 categorical + 1 numerical

WHAT IS A BAR CHART?

A bar chart (also called a bar graph or column chart) is one of the most common and versatile chart types in data visualization. It uses rectangular bars whose length or height is proportional to the values they represent, making it easy to compare quantities across discrete categories. Bar charts are excellent for answering questions like "which category has the highest value?" or "how do these groups compare?" They work with both small and large datasets, and are universally understood by technical and non-technical audiences alike. In R, bar charts are created with ggplot2 using geom_col() for pre-computed values or geom_bar() for count-based data.

HOW TO READ A BAR CHART

Read a bar chart by comparing bar lengths against a common baseline. Because the eye judges length rather than position, the comparison is accurate — which is why bar charts outperform pie charts for ranking. The baseline must be zero: a bar truncated at 40 makes a value of 45 look several times larger than one of 42, since the visible length no longer matches the underlying quantity. Order matters as much as scale. Categories with no natural sequence should be sorted by value so the ranking is readable at a glance; ordinal categories such as survey responses or age bands should keep their own order even where that hides the ranking.

BEST FOR

  • · Comparing quantities across categories
  • · Showing rankings
  • · Survey results
  • · Discrete value comparison

AVOID WHEN

  • · More than 20 categories
  • · Continuous x-axis data
  • · Showing trends over time

R + GGPLOT2 CODE EXAMPLE

ggplot2
ggplot(mtcars, aes(x = factor(cyl), y = mpg)) +
  geom_col(fill = "#ff6a00") +
  labs(title = "MPG by Cylinders", x = "Cylinders", y = "MPG")

SORTED HORIZONTAL BARS WITH VALUE LABELS

The version worth using in a report: sorted by value, flipped so the labels fit, and with the numbers printed on the bars so the reader does not have to measure against the axis.

ggplot2
library(ggplot2)
library(dplyr)
library(forcats)

sales <- data.frame(
  region = c("North", "South", "East", "West", "Central"),
  revenue = c(48200, 71500, 33900, 62300, 55100)
)

ggplot(sales, aes(x = fct_reorder(region, revenue), y = revenue)) +
  geom_col(fill = "#ff6a00", width = 0.7) +
  geom_text(aes(label = scales::comma(revenue)),
            hjust = -0.15, size = 3.5) +
  coord_flip() +
  scale_y_continuous(labels = scales::comma,
                     expand = expansion(mult = c(0, 0.12))) +
  labs(title = "Revenue by region", x = NULL, y = "Revenue (USD)") +
  theme_minimal(base_size = 12) +
  theme(panel.grid.major.y = element_blank())

COMMON MISTAKES WITH THIS CHART

Truncating the y-axis so it does not start at zero

Bars encode value as length, so a non-zero baseline exaggerates differences. Keep the zero and, if the differences are genuinely too small to see, switch to a dot plot or line chart where a truncated axis is legitimate.

Leaving categories in alphabetical or dataset order

Reorder by value with forcats::fct_reorder(category, value). Alphabetical order is almost never the order the reader wants for nominal categories.

Reaching for geom_bar() when the totals are already computed

geom_bar() counts rows; geom_col() plots values. If your data already has one row per category with a total, use geom_col() — the usual symptom of getting this wrong is every bar having height 1.

Rotating labels vertically when there are many categories

Flip the chart instead with coord_flip() or by mapping the category to y. Horizontal bars leave room for full-length labels and stay readable.

Run this code now

Paste the code above into RChat and see the bar chart rendered instantly in your browser.

Try RChat Free →

SIMILAR CHART TYPES

ALTERNATIVES FOR YOUR DATA TYPE