How to Create a Bar Graph in R

Bar graph in R showing labeled categories and horizontal bars

To create a bar graph in R, use base R’s barplot() function when you need a quick chart from category values. Use ggplot2 when you need layered styling, grouped bars, or a consistent plotting workflow.

The key decision is whether your input contains raw observations or values already summarized by category. The same distinction applies to bar graphs in R generally: count raw categories first, but pass precomputed heights directly to the chart.

How do you prepare counts or summarized values?

Raw categorical observations contain one category per record. Convert them to counts with table() before plotting. In contrast, a named numeric vector such as sales already contains the bar heights.

Raw observations:

observations <- c(“Apples”, “Bananas”, “Apples”, “Oranges”, “Bananas”, “Apples”)

counts <- table(observations)

Pre-summarized values for the examples below:

sales <- c(Apples = 12, Bananas = 8, Oranges = 15)

Do not treat a histogram as a substitute for a categorical bar chart. Histograms group numeric measurements into intervals, while bar charts compare named categories. If your data is raw, use table(observations); if the heights are already calculated, use the named vector directly.

How do you create a bar graph in R with barplot()?

Pass the summarized vector to barplot(). The vector names become the category labels. Use main for the title, xlab and ylab for axis labels, and col for bar colors.

barplot(sales, main = “Units sold by fruit”, xlab = “Fruit”, ylab = “Units sold”, col = c(“tomato”, “gold”, “darkorange”))

This produces vertical bars for Apples, Bananas, and Oranges. For raw observations, replace sales with counts. The count values, category names, and their order are then taken from the result of table().

A matrix creates grouped bars. Each column represents a category, and each row represents a series:

grouped <- rbind(Online = c(7, 5, 5), Store = c(5, 3, 10)); colnames(grouped) <- names(sales); barplot(grouped, beside = TRUE, legend.text = rownames(grouped), col = c(“steelblue”, “gray70”))

How do you recreate the chart with ggplot2?

Convert the named vector to a data frame, then map the category column to the x-axis and the value column to the y-axis. geom_col() is appropriate for pre-summarized heights because it uses the supplied values rather than counting rows.

library(ggplot2); sales_df <- data.frame(Fruit = names(sales), Units = as.numeric(sales)); ggplot(sales_df, aes(Fruit, Units)) + geom_col(fill = “steelblue”) + labs(title = “Units sold by fruit”, x = “Fruit”, y = “Units sold”)

For raw observations, use geom_bar(), which counts rows automatically:

ggplot(data.frame(Fruit = observations), aes(Fruit)) + geom_bar(fill = “steelblue”) + labs(x = “Fruit”, y = “Count”)

How does an R bar graph handle labels and orientation?

Set horiz = TRUE in base R to rotate the bars. Use las = 1 to keep the category labels horizontal and readable:

barplot(sales, horiz = TRUE, las = 1, xlab = “Units sold”, ylab = “Fruit”, col = c(“tomato”, “gold”, “darkorange”))

In ggplot2, use coord_flip() after defining the chart:

ggplot(sales_df, aes(Fruit, Units)) + geom_col(fill = “steelblue”) + labs(x = “Fruit”, y = “Units sold”) + coord_flip()

For grouped values in ggplot2, add a grouping column and map it to fill. Use position = “dodge” for side-by-side bars:

grouped_df <- data.frame(Fruit = rep(names(sales), 2), Channel = rep(c(“Online”, “Store”), each = 3), Units = c(7, 5, 5, 5, 3, 10)); ggplot(grouped_df, aes(Fruit, Units, fill = Channel)) + geom_col(position = “dodge”)