I am trying to replicate a figure from this post (How to group a legend or get seperate legends by facets in ggplot2). I am trying to modify this figure to include stat_pointinterval
from the ggdist
package along with a geom_density
rather than a geom_bar
. The geom_density
works fine, but I can't get the stat_interval
to group legend items by facet the same way that geom_density
does. So far, the code below is the best I've been able to achieve, but I would like the stat_intervals
to match the color of their respective densities. The actual data I've been trying to apply this to has many groups, and the number of groups in each facet is inconsistent, so I have not been usual a manual color scale, and I have changed the y axis scale, but otherwise, the code is almost the same as the original example.
library(ggplot2)
library(ggdist)
sub_region_colours <- c("South America" = "#0570b0", "Western Africa" = "#8c96c6", "Central America" = "#74a9cf", "Eastern Africa" = "#8856a7", "Northern Africa" = "#edf8fb", "Middle Africa" = "#b3cde3", "Southern Africa" = "#810f7c", "Northern America" = "#f1eef6", "Caribbean" = "#bdc9e1", "Eastern Asia" = "#bd0026", "Southern Asia" = "#fd8d3c", "South-Eastern Asia" = "#f03b20", "Southern Europe" = "#238b45", "Australia and New Zealand" = "#ce1256", "Melanesia" = "#df65b0", "Micronesia" = "#d7b5d8", "Polynesia" = "#f1eef6", "Central Asia" = "#fecc5c", "Western Asia" = "#ffffb2", "Eastern Europe" = "#66c2a4", "Northern Europe" = "#edf8fb", "Western Europe" = "#b2e2e2", "Small Islands" = "#252525")
d <- structure(list(sender_iso3 = c(
"ABW", "ABW", "ABW", "ABW", "ABW",
"ABW", "ABW", "ABW", "ABW", "ABW", "ABW", "ABW"
), year = c(
2005,
2011, 2014, 2015, 2016, 2017, 2005, 2011, 2014, 2015, 2016, 2017
), sender_region = c(
"Americas", "Americas", "Americas", "Americas",
"Americas", "Americas", "Africa", "Africa", "Africa", "Africa",
"Africa", "Africa"
), sender_subregion = c(
"Caribbean", "Caribbean",
"Caribbean", "Caribbean", "South America", "South America", "Southern Africa",
"Southern Africa", "Southern Africa", "Southern Africa", "Eastern Africa",
"Eastern Africa"
), export = c(
1, 1, 4, 5, 2, 1, 1, 1, 4, 5,
2, 1
)), class = "data.frame", row.names = c(NA, -12L))
regions <- unique(d$sender_region)
# Layers for each region
make_layers <- function(x) {
d <- filter(d, sender_region == regions[[x]])
list(
if (x != 1) new_scale_fill(),
geom_density(data = d, aes(x = year, fill = sender_subregion), alpha = .5, color = NA),
# Below is the problem line:
stat_pointinterval(data = d, aes(x = year, fill = sender_subregion, color = sender_subregion)),
ylim(0,1),
scale_fill_discrete(
guide = guide_legend(
order = x,
title = regions[x],
title.position = "top"
)
)
)
}
p <- ggplot() +
lapply(seq_along(regions), make_layers)
# Add theme and wrap
p +
theme_minimal() +
scale_x_continuous(
name = "Year", limits = c(1986, 2017),
breaks = c(1986, 1990, 2000, 2010, 2017),
guide = guide_axis(angle = 90)
) +
facet_wrap(~sender_region)
In contrast to the code in the post you referenced you have both a fill
and a color
scale. Hence, you have to adapt the code to also add a new color scale using new_scale_color()
and scale_color_xxx
. However, as far you want to apply the same colors the latter can be omitted by applying the fill scale to both color
and fill
using aesthetics = c("fill", "color")
. Additionally I switched to scale_fill_manual
to apply your custom colors.
library(ggplot2)
library(ggdist)
library(dplyr, warn = FALSE)
library(ggnewscale)
# Layers for each region
make_layers <- function(x) {
d <- filter(d, sender_region == regions[[x]])
list(
if (x != 1) new_scale_fill(),
if (x != 1) new_scale_color(),
geom_density(data = d, aes(x = year, fill = sender_subregion), alpha = .5, color = NA),
# Below is the problem line:
stat_pointinterval(data = d, aes(x = year, color = sender_subregion)),
ylim(0, 1),
scale_fill_manual(
values = sub_region_colours,
guide = guide_legend(
order = x,
title = regions[x],
title.position = "top"
),
aesthetics = c("fill", "color")
)
)
}
p <- ggplot() +
lapply(seq_along(regions), make_layers)
#> Scale for y is already present.
#> Adding another scale for y, which will replace the existing scale.
# Add theme and wrap
p +
theme_minimal() +
scale_x_continuous(
name = "Year", limits = c(1986, 2017),
breaks = c(1986, 1990, 2000, 2010, 2017),
guide = guide_axis(angle = 90)
) +
facet_wrap(~sender_region)