Dr.J
Dr.J

Reputation: 25

coloring specific bars of grouped bar chart in r using lattice

I would like to create a bar chart in R using lattice. It's a simple chart with six double columns, currently the color pattern is the same for all of them. That means the first double column is in red and black as well as the other five double columns. Would it be possible to change the color pattern, so that each column has its own color? If it's not possible using lattice, might it be possible with ggplot2? To clarify what I have in mind, see the following two pictures:

Current result:

enter image description here

Desired color pattern:

enter image description here

My current code:

library(lattice)
mitte_table <- read.table(text = "Partei; Jahr; Ergebnis
CDU;2017;18.6
CDU;2013;22.6
SPD;2017;17.9
SPD;2013;26.1
Linke;2017;21.5
Linke;2013;18.7
Gruene;2017;17.2
Gruene;2013;16.7
AfD;2017;8.2
AfD;2013;3.9
FDP;2017;8.7
FDP;2013;3.7
Sonstige;2017;7.9
Sonstige;2013;8.3",
header = TRUE,
sep = ";",
)

colors_Jahr = c("black", "red")

my.settings <- list(
superpose.polygon = list(col = colors_Jahr)
)

barchart(
data = mitte_table,
Ergebnis ~ Partei,
groups = Jahr,
horizontal = FALSE,
main = "Zweitstimme im Wahlkreis Mitte",
xlab = "Parteien",
ylab = "Stimmenverteilung in %",
auto.key = TRUE,
par.settings = my.settings
)

Upvotes: 2

Views: 1130

Answers (1)

Claus Wilke
Claus Wilke

Reputation: 17810

Something like this? (Using ggplot2.)

enter image description here

Two caveats:

  1. I didn't attempt to match the colors to the parties. But that should be easy to fix, just use a different color vector.

  2. It's hard in ggplot2 to get the bars to overlap, as in the example. If you insist on that then some more work is required.

Here is the code:

require(dplyr)
require(ggplot2)

mitte_table <- read.table(text = "Partei; Jahr; Ergebnis
CDU;2017;18.6
CDU;2013;22.6
SPD;2017;17.9
SPD;2013;26.1
Linke;2017;21.5
Linke;2013;18.7
Gruene;2017;17.2
Gruene;2013;16.7
AfD;2017;8.2
AfD;2013;3.9
FDP;2017;8.7
FDP;2013;3.7
Sonstige;2017;7.9
Sonstige;2013;8.3",
header = TRUE,
sep = ";",
)

# make combined dark and light color palette
cols_dark <- c("#CD8E04", "#5E9FC8", "#028D67", "#D6CB35", "#0266A0", "#BB571E", "#AE7192", "#898989")
cols_light <- c("#FFB746", "#7DCCFF", "#4BC095", "#F9ED51", "#579BDB", "#FF834A", "#EC99C6", "#B7B7B7")
colors <- c(rbind(cols_dark, cols_light))

# add a column that has a smaller number for the larger year and vice versa
mitte_table <- mutate(mitte_table, order = 10000 - Jahr)

# reorder levels so they are in the order in which they are in the table
mitte_table$Partei <- factor(mitte_table$Partei, levels = unique(mitte_table$Partei))

# the trick is to fill by a factor that combines the party name and the order (10000 - year)
ggplot(mitte_table, aes(x=Partei, group=order, y=Ergebnis, fill=factor(paste0(Partei,order)))) + 
  geom_col(position="dodge") +
  scale_fill_manual(values = colors,
                    breaks = paste0(mitte_table$Partei[1], 10000-c(2017, 2013)),
                    labels = c("Wahl 2017", "Wahl 2013"),
                    name = "") +
  scale_y_continuous(limits = c(0, 29), expand = c(0, 0)) +
  # override the fill aes to get gray colors in the legend
  guides(fill = guide_legend(override.aes = list(fill = c("#9A9A9A", "#C5C5C5")))) +
  theme_minimal(14) +
  theme(legend.position = "bottom")

Upvotes: 1

Related Questions