0

I'm trying to create a ggplot with bars that are stacked (agreement adding up to 1.0 or 100%) but evaluated over time (x-axis shows time) and for 3 different categories (e.g. types of car). Here is some sample data:

Year <- c(rep(2012, 9), rep(2013, 9), rep(2014, 9))
Car <- rep(c(rep("A", 3), rep("B",3), rep("C",3)),3)
FuelEfficient <- rep(c("Agree", "Neither", "Disagree"),9)
Perception <- c(0.1, 0.3, 0.6, 0.2, 0.3, 0.5, 0.4, 0.1, 0.5, 0.2, 0.4, 0.4, 0.1, 0.3, 0.6, 0.2, 0.3, 0.5, 0.4, 0.1, 0.5, 0.7, 0.1, 0.2, 0.2, 0.6, 0.2)
df <- data.frame(Year, Car, FuelEfficient, Perception)

I am imagining that the cars would each have their own colour, and would appear next to each other at each time point. Each car would then be composed of a bar with 3 different shades of the same colour (representing agreement/disagreement/neither), adding up to 1.0 or 100%. see image 1

I currently have this code:

ggplot(data=df, aes(x=Year, y=Perception, fill=interaction(FuelEfficient,Car), dodge=Car))+
geom_bar(position="fill", stat="identity") +
scale_fill_manual(values=rev(c("#d95f02", "#fc8d62", "#ffb79c", "#7570b3", "#8da0cb", "#b7c7ed", "#1b9e77", "#66c2a5", "#bff5e4")))

which is basically stacking the 3 car types on top of each other at each time point see image 2. This makes it easy to compare trends for each car over time, but not to compare the cars to one another, since each car is at its own level. I had hoped that dodge=Car (present in my code and used here) would solve this problem, but it makes no difference.

This approach could be going in the right direction:

df <- df %>%
mutate(x_label = factor(str_replace(interaction(Year, Car), '\\.', ' / '),
                      ordered = T))
ggplot(df, aes(x=x_label, y=Perception, fill=FuelEfficient)) +
geom_bar(stat='identity') +
scale_fill_manual(values=rev(c("#d95f02", "#fc8d62", "#ffb79c", "#7570b3", "#8da0cb", "#b7c7ed", "#1b9e77", "#66c2a5", "#bff5e4")))

but I would still like to assign different colours to cars A,B,C.

Thanks for any help.

Toni
  • 3
  • 2

1 Answers1

0

Two possible options:

Add , width = 1 to the geom_bar if you want no gap between each bar within each facet.)

library(tidyverse)
library(scales)

Year <- c(rep(2012, 9), rep(2013, 9), rep(2014, 9))
Car <- rep(c(rep("A", 3), rep("B", 3), rep("C", 3)), 3)
FuelEfficient <- rep(c("Agree", "Neither", "Disagree"), 9)
Perception <- c(0.1, 0.3, 0.6, 0.2, 0.3, 0.5, 0.4, 0.1, 0.5, 0.2, 0.4, 0.4, 0.1, 0.3, 0.6, 0.2, 0.3, 0.5, 0.4, 0.1, 0.5, 0.7, 0.1, 0.2, 0.2, 0.6, 0.2)
df <- data.frame(Year, Car, FuelEfficient, Perception)

# Concatenate option
ggplot(df, aes(str_c(Year, " | ", Car), Perception, fill = interaction(FuelEfficient, Car))) +
  geom_bar(position = "fill", stat = "identity") +
  scale_fill_manual(values = rev(c("#d95f02", "#fc8d62", "#ffb79c", "#7570b3", 
                                   "#8da0cb", "#b7c7ed", "#1b9e77", "#66c2a5", "#bff5e4"))) +
  theme(axis.text.x = element_text(angle = 45, hjust = 1)) +
  labs(x = "Year & Car", fill = "Car Fuel\nEfficiency")

# Facet option
ggplot(df, aes(Car, Perception, fill = interaction(FuelEfficient, Car))) +
  geom_bar(position = "fill", stat = "identity") +
  facet_wrap(~ Year) +
  scale_fill_manual(values = rev(c("#d95f02", "#fc8d62", "#ffb79c", "#7570b3", 
                                   "#8da0cb", "#b7c7ed", "#1b9e77", "#66c2a5", "#bff5e4"))) +
  scale_y_continuous(labels = label_percent()) +
  theme(axis.text.x = element_text(angle = 45, hjust = 1)) +
  labs(x = "Year & Car", fill = "Car Fuel\nEfficiency")

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

Carl
  • 4,232
  • 2
  • 12
  • 24