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)
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!")
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:
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)
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)
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())
Related Topics
Why Doesn't "+" Operate on Characters in R
R Looping Through in Survey Package
Click on Points in a Leaflet Map as Input for a Plot in Shiny
What Is the "Embracing Operator" '{{ }}'
Using Melt with Matrix or Data.Frame Gives Different Output
Plot Event Sequences/Event Sequences Clustering
Font Awesome in R, Loaded But Not Found by Waffle
How to Plot a Boxplot from Previously-Calculated Statistics Easily (In R)
Converting Utc Time to Local Standard Time in R
Format Axis Tick Labels to Percentage in Plotly
Converting Date Column in Data Frame
How to Get the First 10 Words in a String in R
R Cmd Check Latex Error: Fatal PDFlatex - Gui Framework Cannot Be Initialized