Color palette with ggplot
To create a reproducible example, I would have to provide shapefile data, etc., and that would be cumbersome for you (loading data, etc.), so here's an attempt, just providing the last part, and what about ggplot
Here's some sample code:
cols <- colorRampPalette(c("darkgreen","yellow","red"), space = "rgb")
myPal <- cols(11)
ggplot(data=df, aes(x=long, y=lat, group=group)) +
geom_polygon(aes(fill = measure))+ # draw polygons
coord_equal() +
scale_x_continuous(breaks = as.numeric(levels(factor(df$measure))))+
scale_fill_manual(values = myPal)+
labs(title="mesure level", x="", y="")+
theme(axis.text=element_blank(),axis.ticks=element_blank())
Basically, I'm trying to apply my own colors to fill regions by specifying a range of colors. The above doesn't work as it throws an error:
Error: Continuous value supplied to discrete scale
EDIT: This works, however:
ggplot(data=df, aes(x=long, y=lat, group=group)) +
geom_polygon(aes(fill = measure))+ # draw polygons
coord_equal() +
geom_path(color="grey", linestyle=2)+
scale_fill_gradient(low = "#ffffcc", high = "#ff4444",
space = "Lab", na.value = "grey50",
guide = "colourbar")+
labs(title="measure level", x="", y="")+
theme(axis.text=element_blank(),axis.ticks=element_blank())
EDIT2: The variable measure
is numeric () and this is how I insert the measure:
df$measure <- as.numeric(round(runif(nrow(df), 0, 1), 1))
dput
is huge, so here str ()
str(df)
'data.frame': 344858 obs. of 8 variables:
$ long : num 18 18 18 18 18 ...
$ lat : num 48.7 48.7 48.7 48.7 48.7 ...
$ order : int 1 2 3 4 5 6 7 8 9 10 ...
$ hole : logi FALSE FALSE FALSE FALSE FALSE FALSE ...
$ piece : Factor w/ 2 levels "1","2": 1 1 1 1 1 1 1 1 1 1 ...
$ group : Factor w/ 80 levels "0.1","1.1","2.1",..: 1 1 1 1 1 1 1 1 1 1 ...
$ id : chr "0" "0" "0" "0" ...
$ measure: num 0.7 0.4 0.8 0.8 0.8 0.2 0.8 0.5 0.2 0 ...
source to share
Uh-huh. scale_fill_gradient
is continuous. scale_fill_manual
is discrete and is measure
definitely numeric (and not a factor), so what you see is completely expected behavior. Here's an example toy to help explain:
library(rgdal)
library(curl)
library(ggplot2)
library(ggthemes)
# get a simple shapefile
map_url <- "https://andrew.cartodb.com/api/v2/sql?filename=us_states_hexgrid&q=SELECT+*+FROM+andrew.us_states_hexgrid&format=geojson&api_key="
res <- curl_fetch_disk(map_url, "hexes.json")
hex <- readOGR("hexes.json", "OGRGeoJSON")
## OGR data source with driver: GeoJSON
## Source: "hexes.json", layer: "OGRGeoJSON"
## with 51 features
## It has 6 fields
str(hex@data)
## 'data.frame': 51 obs. of 6 variables:
## $ cartodb_id: int 1219 1217 1218 220 215 228 232 227 230 229 ...
## $ created_at: Factor w/ 4 levels "2015-05-13T22:02:22Z",..: 4 2 3 1 1 1 1 1 1 1 ...
## $ updated_at: Factor w/ 51 levels "2015-05-14T14:17:56Z",..: 20 40 47 12 44 2 3 11 19 25 ...
## $ label : Factor w/ 51 levels "A.K.","Ala.",..: 20 40 47 12 44 2 3 11 19 25 ...
## $ bees : num 60.5 47.8 33.9 13.9 46.3 48.1 42.9 34.9 44.3 38.7 ...
## $ iso3166_2 : Factor w/ 51 levels "AK","AL","AR",..: 22 40 47 12 44 2 4 11 19 26 ...
We will use bees
it since it is similar to yours measure
.
# make it so we can use the polygons in ggplot
hex_map <- fortify(hex, region="iso3166_2")
str(hex_map)
## 'data.frame': 357 obs. of 7 variables:
## $ long : num -133 -130 -130 -133 -135 ...
## $ lat : num 55.3 54.4 52.5 51.6 52.5 ...
## $ order: int 1 2 3 4 5 6 7 8 9 10 ...
## $ hole : logi FALSE FALSE FALSE FALSE FALSE FALSE ...
## $ piece: Factor w/ 1 level "1": 1 1 1 1 1 1 1 1 1 1 ...
## $ group: Factor w/ 51 levels "AK.1","AL.1",..: 1 1 1 1 1 1 1 2 2 2 ...
## $ id : chr "AK" "AK" "AK" "AK" ...
It bees
will be considered a continuous variable by default, and the default fill color scale will reflect this:
gg <- ggplot()
gg <- gg + geom_map(data=hex_map, map=hex_map,
aes(x=long, y=lat, map_id=id),
fill="#ffffff", color="#7f7f7f", size=0.25)
gg <- gg + geom_map(data=hex@data, map=hex_map, aes(map_id=iso3166_2, fill=bees))
gg <- gg + coord_map()
gg <- gg + theme_map()
gg <- gg + theme(legend.position="right")
gg
You can have ggplot's use of automatic cuts and a discrete color palette versus a continuous color map with scale_fill_distiller
:
gg <- ggplot()
gg <- gg + geom_map(data=hex_map, map=hex_map,
aes(x=long, y=lat, map_id=id),
fill="#ffffff", color="#7f7f7f", size=0.25)
gg <- gg + geom_map(data=hex@data, map=hex_map, aes(map_id=iso3166_2, fill=bees))
gg <- gg + scale_fill_distiller()
gg <- gg + coord_map()
gg <- gg + theme_map()
gg <- gg + theme(legend.position="right")
gg
You can also do manual cut outside of ggplot operations and pass this new column to scale_fill_manual
.
If you must use a continuous color gamut, consider using the viridis color map:
devtools::install_github("sjmgarnier/viridis")
library(viridis)
gg <- ggplot()
gg <- gg + geom_map(data=hex_map, map=hex_map,
aes(x=long, y=lat, map_id=id),
fill="#ffffff", color="#7f7f7f", size=0.25)
gg <- gg + geom_map(data=hex@data, map=hex_map, aes(map_id=iso3166_2, fill=bees))
gg <- gg + coord_map()
gg <- gg + scale_fill_viridis()
gg <- gg + theme_map()
gg <- gg + theme(legend.position="right")
gg
It is more accurate overall, accurately visible to the blind and grayscale downscaling (and accurate).
source to share
With scale_manual
you "[c] re-create your own discrete scale" ( ?scale_fill_manual
). Thus, the error "Error: continuous value [ie" The measurement "] is fed to the discrete scale [ scale_fill_manual
]".
You need a continuous scale and give it a try scale_fill_gradient
. Good. However, it would be easier to achieve the desired palette by using scale_fill_gradientn
that creates a "Smooth Color Gradient Between n Colors".
A simpler example:
# some data
df <- data.frame(x = 1:11, y = 1)
# an analogue to your failed attempt
ggplot(data = df, aes(x = x, y = y, fill = x)) +
geom_point(pch = 21, size = 20) +
scale_fill_manual(values = myPal)
# Error: Continuous value supplied to discrete scale
# using the continuous scale_fill_gradientn instead, with the desired color vector and space
ggplot(data = df, aes(x = x, y = y, fill = x)) +
geom_point(pch = 21, size = 20) +
scale_fill_gradientn(colours = c("darkgreen", "yellow", "red"), space = "rgb")
source to share