I'm plotting a heatmap for countries of the world based on number of publications for a research topic. The map is almost working, but the color bar won't behave... I want 0 values to be grey and subsequent bins to follow a green gradient. The palette I'm using has worked in other ggplot applications, but I can't get it to work with scale_fill_stepsn or any of the associated functions. Why won't this plot one grey bin and the green gradient for the remaining bins?
Data used:
# Load the necessary libraries
library(ggplot2)
library(sf)
library(dplyr)
library(rnaturalearth)
library(rnaturalearthdata)
# Load world map data (countries and continents)
world <- ne_countries(scale = "medium", returnclass = "sf")
Plus an added column "Publications" with the number of publications for each country.
Code:
# Define the color palette for the bins (light grey to dark green)
# Create color palette
green_palette <- colorRampPalette(c("#ADBC9F", "#12372A"))(6)
custom_palette <- c("#B4B4B8", green_palette)
first_color <- "#B4B4B8" # Gray color for 0 values
# Create a world map with countries color-coded by number of publications using binned colors
map_countries <- ggplot(world_data) +
geom_sf(aes(fill = Publications), color = "white") + # Color by publications
scale_fill_stepsn(
breaks = c(0, 1, 5, 10, 25, 50, 75, Inf), # Define bin breaks
colors = c(first_color, green_palette), # First color is gray, rest are green gradient
na.value = first_color # Handle NA values with the same gray color
) +
# Adjust the legend appearance
guides(
fill = guide_coloursteps(
even.steps = TRUE,
show.limits = TRUE,
barwidth = unit(15, 'cm'), # Adjust the width of the colorbar
title = "Publications" # Optional: Add title to colorbar
)
) +
theme_minimal() +
theme(
legend.position = "bottom",
legend.key.height = unit(1, "cm"),
legend.title = element_text(face = "bold"),
legend.spacing = unit(0.25, "cm"),
legend.justification = "center",
plot.title = element_text(hjust = 0.5)
) +
# Customize the legend and colorbar appearance
#theme_minimal() +
labs(
title = "World Map: Publications by Country (Binned Colorbar)",
subtitle = "Total number of publications per country"
) +
# Change projection
coord_sf(crs = "+proj=robin") # Use the Robinson projection
# Print country map
print(map_countries)
The plot being producted:
The color bar should look like this:
Thank you.
If you want a binned scale where
colours should not be evenly positioned along the gradient
then you have to pass vector to the values=
argument where
the vector gives the position (between 0 and 1) for each colour in the colours vector.
However, for your desired result you might simply bin the variable mapped on fill
manually and use scale_fill_manual
:
library(ggplot2)
library(rnaturalearth)
library(rnaturalearthdata)
#>
#> Attaching package: 'rnaturalearthdata'
#> The following object is masked from 'package:rnaturalearth':
#>
#> countries110
world <- ne_countries(scale = "medium", returnclass = "sf")
green_palette <- colorRampPalette(c("#ADBC9F", "#12372A"))(6)
custom_palette <- c("#B4B4B8", green_palette)
first_color <- "#B4B4B8" # Gray color for 0 values
set.seed(123)
world_data <- world
world_data$Publications <- sample(200, nrow(world), replace = TRUE)
breaks <- c(0, 1, 5, 10, 25, 50, 75, Inf)
world_data$pub_cut <- cut(
world_data$Publications,
breaks = breaks,
right = TRUE,
include.lowest = TRUE
)
ggplot(world_data) +
geom_sf(
aes(fill = pub_cut),
color = "white",
show.legend = TRUE
) +
scale_fill_manual(
values = c(first_color, green_palette),
labels = c(
0, "1 - 5", "6 - 10", "11 - 25", "26 - 50", "51 - 75",
"76+"
),
drop = FALSE
) +
guides(
fill = guide_legend(
title = "Publications",
theme = theme(
legend.text.position = "bottom",
legend.key.width = unit(1.5, "cm"),
legend.key.height = unit(1, "cm"),
legend.key.spacing.x = unit(0, "pt")
),
override.aes = list(linewidth = 0, color = NA),
nrow = 1
)
) +
theme_minimal() +
theme(
legend.position = "bottom",
legend.title = element_text(face = "bold"),
legend.justification = "center",
plot.title = element_text(hjust = 0.5)
) +
labs(
title = "World Map: Publications by Country (Binned Colorbar)",
subtitle = "Total number of publications per country"
) +
coord_sf(crs = "+proj=robin") # Use the Robinson projection