I am trying to create different bar graphs within a loop showing counts per species and regions, faceting by regions. The structure of my df it's something like:
# Sample data frame structure
max_counts <- data.frame(
Region = c("Eco1", "Eco1", "Eco2", "Eco2"),
Date = c(1, 2, 1, 2),
max_count = c(10, 15, 8, 12),
rounded_max_count = c(10, 15, 10, 15)
)
# Replicate the data frame for multiple species
species_list <- c("Sp1", "Sp2", "Sp3")
max_counts_list <- list()
for (species in species_list) {
max_counts_species <- max_counts
max_counts_species$Species <- species
max_counts_list[[length(max_counts_list) + 1]] <- max_counts_species
}
# Combine the replicated data frames into one
max_counts_df <- do.call(rbind, max_counts_list)
I want the y axis of each facet to be its own and nota common y axis shared as in some regions there are many records and in others just a few. Since many attempts have given me bars reaching the top of the facet and I wanted some padding I created a column rounding the maximum value to the nearest multiple of 5. I need now the y max label on each region to be the rounded ymax value on that particular region. I have tried many things but the closes approach looks like this:
# Create the plot
plot <- ggplot(max_counts, aes(x = Date, y = max_count, fill = Region)) +
geom_bar(stat = "identity") +
scale_fill_manual(values = mycolors) +
facet_wrap(~ Region, ncol = 1, scales = "free_y") +
scale_x_continuous(breaks = seq(min(filtered_ecoregions$Date), max(filtered_ecoregions$Date), by = 1)) +
scale_y_continuous(breaks = seq(0, max(max_counts$rounded_max_count), by = 5), expand = c(0, 0.01)) +
theme_bw()
But it is not quite doing it... my attempts either create a common y axis for all facets or show the individual ones but the ymax label is not displayed.
Any advice would be welcome! Thanks
The issue is that only breaks=
which fall inside the limits=
of the scale will be displayed. Hence, for all panels where rounded_max_count
is larger than max(max_count)
your desired "maximum" value will not be displayed.
Besides of that, if you want to set the limits=
individually per panel I would suggest to have a look at the ggh4x
package which via ggh4x::facetted_pos_scales
allows to specify positional scales (including the limits=
) individually per panel.
library(ggplot2)
library(ggh4x)
# Create a list of y scales per panel
scale_y <- max_counts |>
split(~Region) |>
lapply(\(x) {
scale_y_continuous(
breaks = seq(0, max(x$rounded_max_count), by = 5), expand = c(0, 0.01),
limits = c(0, max(x$rounded_max_count))
)
})
ggplot(max_counts, aes(x = Date, y = max_count, fill = Region)) +
geom_bar(stat = "identity") +
#scale_fill_manual(values = mycolors) +
#scale_x_continuous(breaks = seq(min(filtered_ecoregions$Date), max(filtered_ecoregions$Date), by = 1)) +
scale_x_continuous(breaks = scales::breaks_width(1)) +
facet_wrap(~Region, ncol = 1, scales = "free_y") +
ggh4x::facetted_pos_scales(
y = scale_y
) +
theme_bw()