问题
I'm trying to fill a combined categorical and continuous variable on a map. So, for instance, in my minimally reproducible example below, say I want to display the number of KrispyKreme Donut shops in each county, which is generally a continuous variable I want to fill on a gradient. But I also have counties that forbid KrispyKremes indicated by a "-1" and those that have them under construction "-2". I want to display these in a different color not mapped on the gradient. I also have NA in my real data.
--What I have so far:
library(sf)
library(ggplot2)
nc <- st_read(system.file("shape/nc.shp", package="sf"))
nc$Status<-rep(c(-2,-1,runif(8)), 10)
ggplot(nc) +
geom_sf(aes(fill=Status),color = "black") +
coord_sf(datum = NA) +
theme_minimal()
It breaks if I add the following line, obviously. So, I know I have the syntax wrong but it indicates what I want to do in as best as I can figure code for this
scale_fill_manual(breaks= c("-2","-1", >=0),values = c("blue", "yellow", scale_fill_viridis()))
Any help is much appreciated, I've been on this all day.
回答1:
You will need to cut your continuous variable into different categories.
library(sf)
library(ggplot2)
library(dplyr)
# Set seed for reproducibility
set.seed(122)
nc <- st_read(system.file("shape/nc.shp", package="sf"))
nc$Status<-rep(c(-2,-1,runif(8)), 10)
First, check the distribution of your variable.
nc %>%
filter(Status >= 0) %>%
pull("Status") %>%
summary()
# Min. 1st Qu. Median Mean 3rd Qu. Max.
# 0.002789 0.153144 0.602395 0.491287 0.735787 0.906851
I decided to cut the variable based on the quantile as follows.
nc2 <- nc %>%
mutate(Status2 = case_when(
Status == -2 ~ "-2",
Status == -1 ~ "-1",
Status >= 0 & Status < 0.15 ~ "0 - 0.15",
Status >= 0.15 & Status < 0.6 ~ "0.15 - 0.6",
Status >= 0.6 & Status < 0.75 ~ "0.6 - 0.75",
Status >= 0.75 ~ "0.75 - 0.91"
))
Now Status2
is a categorical variable. We can plot it and use scale_fill_manual
to provide colors. Notice that we need to provide the color code in the values
argument. viridis::viridis(4)
is to generate four colors based on the viridis.
ggplot(nc2) +
geom_sf(aes(fill=Status2),color = "black") +
coord_sf(datum = NA) +
theme_minimal() +
scale_fill_manual(values = c("blue", "yellow", viridis::viridis(4)))
回答2:
Many thanks for this. The way Status2
was constructed above makes it a character variable. I would like to plot a categorical variable instead. The code below generates a factor variable instead (Status3
) and plots it in the map. It works.
library(sf)
library(ggplot2)
library(dplyr)
nc <- st_read(system.file("shape/nc.shp", package="sf"))
nc$Status<-rep(c(-2,-1,runif(8)), 10)
nc3 <- nc %>%
mutate(Status3 = factor(ifelse(Status>0,1,0)))
ggplot(nc3) +
geom_sf(aes(fill=Status3),color = "black") +
coord_sf(datum = NA) +
theme_minimal()
However, when I try to do apply the same rationale (construct a factor variable based on a continuous variable and plot it a map) to my code I get an error.
Error in if (type == "point") { : argument is of length zero
My code is below. The code works when plotting the continuous variable but not when plotting the factor variable. Does anyone know why?
# plotting continuous variable: WORKS FINE
ggplot(CS_mun_shp)+
geom_sf(aes(geometry=geometry,
fill=ppc_sih),
color=NA)
# constructing factor variable
CS_mun_shp2 <- CS_mun_shp %>%
mutate(cs_above40=factor(ifelse(ppc_sih>=0.4,1,0),
levels=c(0:1),
labels=c('below 40%','above 40%')))
# plotting factor variable: GENERATES ERROR
ggplot(CS_mun_shp2)+
geom_sf(aes(geometry=geometry,
fill=cs_above40),
color=NA)
The only difference between my code and the reproduceable example above is that I need to specify geometry
inside aes()
, otherwise I get another error.
来源:https://stackoverflow.com/questions/53126643/combine-categorical-and-gradient-fill-in-geospatial-r