JFD
JFD

Reputation: 339

ggplot color scale rendering incorrectly

I am working to use r's ggplot to recreate a graphic originally created in python. The graphic uses a color scale specified via RGB colors. When I create my graphic using the same RGB colors they don't render properly in my Windows 10/Rstudio set up. Below I show the legend rendered correctly and the rendering my r script produces. It seems there is too much yellow coming through the colors.

I don't know where to begin to try to determine why the specified colors are not rendering into the same colors as the example image that I have. What suggestions do you have to try to troubleshoot this?

enter image description here

My reproducible example is below.

library(urbnmapr)
library(ggplot2)
library(dplyr)
library(ggthemes)

# Set colors 
red   <- c(0.67, 0.75, 0.84, 0.92, 1,    1,    0.8, 0.53, 0,   0,    0,   0)
green <- c(0.25, 0.4,  0.56, 0.71, 0.86, 1,    1,   0.95, 0.9, 0.75, 0.6, 0.48)
blue  <- c(0.11, 0.18, 0.25, 0.33, 0.4,  0.45, 0.4, 0.27, 0,   0,    0,   0)

# Obtain county polygon data
states_sf <- get_urbn_map(map = "states", sf = TRUE)
counties_sf <- get_urbn_map(map = "counties", sf = TRUE)

# Assign random values of data to each count  
counties_sf$value = runif(length(counties_sf$county_fips), min=-3.0, max=3.0)

# Remove AK and HI - lower 48 only 
states_sf <- states_sf[!(states_sf$state_abbv %in% c("HI","AK")),]
counties_sf <- counties_sf[!(counties_sf$state_abbv %in% c("HI","AK")),]

# Plot county level data with a discrete legend 

data_levels <- c(-3,-1.5, -0.8, -0.5, -0.25,-0.1,0.1,0.25,0.5,.8,1.5,3)
level_colors <- rgb(red, green, blue)

length(data_levels)
length(level_colors)

counties_sf %>%
  ggplot() +
  # Overlay State Outlines
  # Plot county data and fill with value
  geom_sf(mapping = aes(fill = value), color = NA) +
  geom_sf(data = states_sf, fill = NA, color = "black", size = 0.25) +
  # Remove grid lines from plot
  coord_sf(datum = NA) +   
  scale_fill_stepsn(breaks=data_levels, colors=level_colors, limits=c(-3,3), 
                    labels=scales::label_number(accuracy=0.1)) + 
  labs(title='This Data is Completely Random', 
       fill ='The Legend') + 
  theme_map() + 
  theme(legend.position = "bottom",
        legend.key.width=unit(1.5,"cm"),
        legend.box.background = element_rect(color="black", size=2),
        legend.title = element_text(face = "bold"),
        legend.spacing = unit(0.25,"cm"),
        legend.justification = "center",
        plot.title=element_text(hjust=0.5))  +
  guides(fill = guide_bins(title.position="top", title.hjust = 0.5,
                           keywidth=unit(20,'points'), axis=FALSE,
                           axis.linewidth=unit(3,'points')))

Upvotes: 1

Views: 263

Answers (2)

TarJae
TarJae

Reputation: 78917

Is this the plot you are looking for? Use n.breaks=12

Replace

scale_fill_stepsn(breaks=data_levels, colors=level_colors, limits=c(-3,3), labels=scales::label_number(accuracy=0.1)) +

with

scale_fill_stepsn(n.breaks=12, colors=level_colors, limits=c(-3,3), labels=scales::label_number(accuracy=0.1)) +

enter image description here

When I run your code I get this plot. enter image description here

Upvotes: 2

arvi1000
arvi1000

Reputation: 9582

Looks like perhaps you aren't using all the levels? I didn't install the urbnmapr package to run your example, but when I run this more minimal example the colors look about right.

# Set colors 
red   <- c(0.67, 0.75, 0.84, 0.92, 1,    1,    0.8, 0.53, 0,   0,    0,   0)
green <- c(0.25, 0.4,  0.56, 0.71, 0.86, 1,    1,   0.95, 0.9, 0.75, 0.6, 0.48)
blue  <- c(0.11, 0.18, 0.25, 0.33, 0.4,  0.45, 0.4, 0.27, 0,   0,    0,   0)
level_colors <- rgb(red, green, blue)

library(ggplot2)
ggplot(data.frame(x=level_colors, y=1),
       aes(x=level_colors, y=1, fill=level_colors)) +
  geom_col() +
  scale_fill_manual(values = level_colors)

enter image description here

Note that if not all the levels are present in the data, they don't all show up.

ggplot(data.frame(x=level_colors[1:5], y=1),
       aes(x=x, y=y, fill=factor(x))) +
  geom_col() +
  scale_fill_manual(values = level_colors)

enter image description here

But you can force them to show in legend with drop = FALSE in the scale call:

dat <- data.frame(x=factor(level_colors, levels=level_colors), y=1)
ggplot(dat[1:5,], aes(x=x, y=y, fill=x)) +
  geom_col() +
  scale_fill_manual(values = level_colors, drop=F)

enter image description here

Upvotes: 2

Related Questions