How to Plot a Stacked Bar with Ggplot

How to implement stacked bar graph with a line chart in R

You first need to reshape longer, for example with pivot_longer() from tidyr, and then you can use ggplot2 to plot the bars and the line in two separate layers. The fill = argument in the geom_bar(aes()) lets you stratify each bar according to a categorical variable - name is created automatically by pivot_longer().

library(ggplot2)
library(tidyr)

dat |>
pivot_longer(A:B) |>
ggplot(aes(x = Year)) +
geom_bar(stat = "identity", aes(y = value, fill = name)) +
geom_line(aes(y = `C(%)`), size = 2)

Sample Image

Created on 2022-06-09 by the reprex package (v2.0.1)

You're asking for overlaid bars, in which case there's no need to pivot, and you can add separate layers. However I would argue that this could confuse or mislead many people - usually in stacked plots bars are stacked, not overlaid, so thread with caution!

library(ggplot2)
library(tidyr)

dat |>
ggplot(aes(x = Year)) +
geom_bar(stat = "identity", aes(y = A), fill = "lightgreen") +
geom_bar(stat = "identity", aes(y = B), fill = "red", alpha = 0.5) +
geom_line(aes(y = `C(%)`), size = 2) +
labs(y = "", caption = "NB: bars are overlaid, not stacked!")

Sample Image

Created on 2022-06-09 by the reprex package (v2.0.1)

How to create a stacked bar chart in r with ggplot

This probably serves your purpose:

library(tidyverse)
mydata %>% pivot_longer(cols = !sample, names_to = "status", values_to = "percentage") %>%
ggplot(aes(fill = status, x = sample, y = percentage)) +
geom_bar(position = "stack", stat = "identity")

The result:
Sample Image

Stacked bar plot with ggplot2

You should add rownames as a variable in your data frame, and transform your data to long format so ggplot can handle it. Something like this is close to what you mean I think:

yourDataFrame %>% 
mutate(Label = rownames(df)) %>% # add row names as a variable
reshape2::melt(.) %>% # melt to long format
ggplot(., aes(x = Label, y = value, fill = variable)) +
geom_bar(stat='identity')

How to make single stacked bar chart in ggplot2?

You need to create a dummy variable for x-axis. Then use geom_col which is similar to geom_bar(stat = "identity") to plot the stacked barplot + geom_text to put the text on the bar.

The plot you showed used theme_economist from the ggthemes package.

library(tidyverse)

Ancestry <- data.frame(Race = c("European", "African American", "Asian", "Hispanic", "Other"),
Proportion = c(40, 30, 10, 15, 5))

Ancestry <- Ancestry %>%
mutate(Year = "2006")

ggplot(Ancestry, aes(x = Year, y = Proportion, fill = Race)) +
geom_col() +
geom_text(aes(label = paste0(Proportion, "%")),
position = position_stack(vjust = 0.5)) +
scale_fill_brewer(palette = "Set2") +
theme_minimal(base_size = 16) +
ylab("Percentage") +
xlab(NULL)

Sample Image

library(ggthemes)

ggplot(Ancestry, aes(x = Year, y = Proportion, fill = Race)) +
geom_col() +
geom_text(aes(label = paste0(Proportion, "%")),
position = position_stack(vjust = 0.5)) +
theme_economist(base_size = 14) +
scale_fill_economist() +
theme(legend.position = "right",
legend.title = element_blank()) +
theme(axis.title.y = element_text(margin = margin(r = 20))) +
ylab("Percentage") +
xlab(NULL)

Sample Image

Created on 2018-08-26 by the reprex package (v0.2.0.9000).

Staggering labels or adding only selected labels on ggplot stacked bar chart

If I were you, I'll only display labels for Pct greater than 5% using if_else() in geom_text(aes()). If it's less than 5%, display nothing.

Also, since your geom_bar position is fill, you should also use position = position_fill() in geom_text to align the position.

library(tidyverse)

data %>%
select(q1a:q1b) %>%
pivot_longer(cols = everything(), names_to = "Question") %>%
filter(!is.na(value)) %>%
dplyr::count(Question, value) %>%
group_by(Question) %>%
mutate(Pct = n / sum(n)) %>%
ggplot(aes(fill = value, x = Pct, y = fct_rev(Question))) +
geom_bar(position = "fill", stat = "identity") +
geom_text(aes(label = if_else(Pct > 0.05, paste0(sprintf("%1.0f", Pct * 100), "%"), NULL)),
position = position_fill(vjust = 0.5), size = 3) +
scale_fill_brewer(palette = "Blues") +
theme_bw() +
scale_x_continuous(labels = scales::percent) +
labs(title = "Question 1", y = "Question", x = "Percentage") +
theme(legend.title = element_blank())

labelPCT



Related Topics



Leave a reply



Submit