I am making a map that needs to 2 legends. 1 legend shows the temperature, and another legend shows if points are labelled as zone 1:4. When I try to add the second color scale, for the second legend I get the error
Scale for 'fill' is already present. Adding another scale for
'fill', which will replace the existing scale.
Error: Continuous value supplied to discrete scale
When I don't specify the second color scale I get the map I want however, the points are not the colour I want them to be. I tried using new_scale_color() in the code but that doesn't work either, it's the same error.
Here is some sample data
#Dataframe for Ocean Temperature
mapoc_temp = expand.grid(data.frame(Longitude= seq(-64.5,-62.4,0.1),
Latitude= seq(42.7,44.8,0.1),
year = sample(c(2016,2017,2018), 22, replace = T),
month = sample(month.abb, 22, replace = T)))
mapoc_temp$Ave = runif(nrow(mapoc_temp))
#Dataframe for the points
individual_dets = data.frame(longitude= seq(-64.5,-62.4,0.1),
latitude= seq(42.7,44.8,0.1),
year = sample(c(2016, 2017, 2018), 22, replace = T),
Zone = sample(c(1:4), 22, replace = T),
month = sample(month.abb, 22, replace = T))
This is the code I use to map it, you will need this entire code to see my error.
library(mapdata)
#Import Canada map
canada = map_data("worldHires", "Canada")
## Map of temperature across Scotian Shelf
ggplot(mapoc_temp, aes(x=Longitude, y=Latitude)) +
#plotting the temperature as color
geom_raster(aes(fill = Ave,
x = Longitude), interpolate = TRUE) +
#getting the map of Scotian shelf
geom_polygon(data = canada,
aes(x=long, y=lat, group=group),
colour="grey50", fill = 'grey55')+
#Coordinates I'm interested in looking at
coord_sf(xlim=c(-64.5,-62.8), ylim=c(42.7,45)) +
scale_fill_viridis_c(name = "Temp.\n(°C)", option = "C") +
#Use this to get second legend?
new_scale_color() +
#to try and get zones overtop
geom_point(data = individual_dets,
aes(x = longitude,
y = latitude,
color = as.numeric(Zone),
fill = as.numeric(Zone)),
pch = 21, size = 2) +
#fill the zones with second legend.... Does not work
scale_fill_manual(values=c("#01579B", "#4FC3F7", "#ffa600", "#ff6361")) +
scale_color_manual(values=c("#01579B", "#4FC3F7", "#ffa600", "#ff6361"))
If I don't use the last chunk of code
#fill the zones with second legend.... Does not work
scale_fill_manual(values=c("#01579B", "#4FC3F7", "#ffa600", "#ff6361")) +
scale_color_manual(values=c("#01579B", "#4FC3F7", "#ffa600", "#ff6361"))
I get this picture
But I need the points to be those exact colors I have in the chunk of code. Does anyone know how to add the second legend scale to the ggplot map?
If you don't use a pch = 21, ggplot will use a point with color being the same fill (I guess it is pch = 16 by default), so, you don't need twice scale_fill but instead can manipulate points using scale_color_manual.
Also, you are converting Zone in a numeric format so ggplot2 is plotting it as a continuous scale. So, you can't pass only 4 color values on it. Either, you have to plot Zone as a factor and use scale_color_manual to set the color for each zone (which makes sense) or you can plot Zone as a gradient as you are doing but you need to use scale_color_gradient then to set the color scheme.
library(mapdata)
library(ggplot2)
ggplot(mapoc_temp, aes(x=Longitude, y=Latitude)) +
geom_raster(aes(fill = Ave,
x = Longitude), interpolate = TRUE) +
geom_polygon(data = canada,
aes(x=long, y=lat, group=group),
colour="grey50", fill = 'grey55')+
coord_sf(xlim=c(-64.5,-62.8), ylim=c(42.7,45)) +
scale_fill_viridis_c(name = "Temp.\n(°C)", option = "C") +
geom_point(data = individual_dets,
aes(x = longitude,
y = latitude,
color = as.factor(Zone)),
#fill = as.numeric(Zone)),
size = 2) +
scale_color_manual(values=c("#01579B", "#4FC3F7", "#ffa600", "#ff6361"), name = "Zone")
Does it look what you are trying to achieve ?
Related
I’m currently trying to display my data on a map as points. In fact I got two different data sets of two different studies which I’d like to combine on the map. But my first problem was where to find a map to use for my purpose.
#In the R graphics Cookbook I read about this code to create a map using the ggplot2 package
library(ggplot2)
library(maps)
states_map <- mapd_data(“state”)
ggplot(states_map, aes(x=long, y=lat, group=group)) +
geom_polygon(fill=”white”, colour=”black”) +
#Then I added the data of my two data sets and it worked perfectly fine.
geom_point(data = dat1, aes(x = longitude, y = latitude, group= NA), shape=21, col = "black", fill=”red”, size = dat1$var1) +
geom_point(data = dat2, aes(x = longitude, y = latitude, group= NA), shape=21, col = "black", fill=”blue”, size = dat2$var2)
Now I want to add two legends, one to explain the difference between the point colors and the other to explain the point size. Both data sets can share the same legend for the point size because Var1 and Var2 are on the same scale. But I don’t know how to add custom legends to a ggplot (I even don’t achieve to add any legend to the ggplot). It would be nice to have anything like legend()-function which adds a legend to a normal plot, but I think ggplot wasn’t programmed to solve problems like this on your own. Another approach to solve the problem could be to plot the map without using ggplot.
If you want a legend then you have to map on an aesthetic, i.e. move fill=... and size=... inside aes(). After doing so you could set your desired fill colors via scale_fill_manual:
library(ggplot2)
library(maps)
states_map <- map_data("state")
dat1 <- data.frame(longitude = -110, latitude = 35, var1 = 100)
dat2 <- data.frame(longitude = -90, latitude = 40, var2 = 200)
ggplot(states_map, aes(x=long, y=lat)) +
geom_polygon(aes(group=group), fill="white", colour="black") +
geom_point(data = dat1, aes(x = longitude, y = latitude, fill = "dat1", size = var1), shape=21, col = "black") +
geom_point(data = dat2, aes(x = longitude, y = latitude, fill = "dat2", size = var2), shape=21, col = "black") +
scale_fill_manual(values = c(dat1 = "red", dat2 ="blue"), labels = c(dat1 = "Data 1", dat2 ="Data 2"))
I have the following:
set.seed(100)
df <- data.frame(
lng = runif(n=20, min=5, max=10),
lat = runif(n=20, min=40, max=50),
year = rep(c("2001","2002","2003","2004"), each=5),
season = sample(c("spring", "autumn"), 10, replace = T),
info = sample(c("yes","no"), 10, replace = T)
)
Which can be plotted by:
ggplot() +
geom_point(data=df,
aes(x = lng,
y = lat,
color = year,
shape = season),
size=3)
To produce:
Great. But I want a red outline on the shapes were info == "yes".
The desired output would be:
Not made using actual data, just for demonstrative purpose. Made in powerpoint.
Admittedly it is similar to this question here, but not quite.
I am happy to split the df using a filter if easier then two + geom_points()
Many thanks
Jim
Below is a quick solution (not the best), which is to use another scale, and below I use size as the scale, then use guides() to manually specify the shape to appear in the legend. you need to plot the bigger red shapes first and then plot over so that it looks like an outline:
ggplot() +
geom_point(data=subset(df,info=="yes"),
aes(x=lng,y=lat,shape = season,size=info),col="red") +
scale_size_manual(values=3.6)+
geom_point(data=df,
aes(x = lng,
y = lat,
color = year,
shape = season),
size=3)+
guides(size = guide_legend(override.aes = list(shape = 1)))
You can change the legend for the shape by playing around with options in the guide()
I have a map with some points across it that were created with geom_point. They are in the exact location and color I need them to be, but I am trying to change the shape to a silhouette I imported from phylopic. Here is some sample data for the code
#Dataframe for the points
individual_dets = data.frame(longitude= seq(-64.5,-62.4,0.1),
latitude= seq(42.7,44.8,0.1),
year = sample(c(2016, 2017, 2018), 22, replace = T),
Zone = sample(c(1:4), 22, replace = T),
month = sample(month.abb, 22, replace = T))
Below is the code for my imported phylopic silhouette, and my code for the map with the points on it
library(rphylopic)
library(RCurl)
library(png)
library(mapdata)
#Import phylopic
rayurl = "http://phylopic.org/assets/images/submissions/a3b3e80c-22f2-4b8f-a3ac-42fe1583e0be.thumb.png"
raylogo = readPNG(getURLContent(rayurl))
#Importing the map
canada = map_data("worldHires", "Canada")
#The Map
ggplot() +
geom_polygon(data = canada,
aes(x=long, y=lat, group=group),
colour="grey50", fill = 'grey55')+
#Coordinates I'm interested in looking at
coord_sf(xlim=c(-64.5,-62.8), ylim=c(42.7,45)) +
geom_point(data = individual_dets,
aes(x = longitude,
y = latitude,
color = as.factor(Zone)),
#fill = as.numeric(Zone)),
size = 5) +
scale_color_manual(values=c("#01579B", "#4FC3F7", "#ffa600", "#ff6361"),
name = "Zone")
Does anyone know how to take this saved silhouette and place it at the same coordinate and as the same color of my points?
I've been plotting two sets of positional data with geom_point from different data sets (MR + MRTag).
MR
detect_date Latitude Longitude species
12/04/2016 11:08 -6.6524 71.3475 Manta Ray
12/04/2016 11:09 -6.6524 71.3475 Manta Ray
12/04/2016 11:10 -6.6524 71.3475 Manta Ray
16/04/2016 21:27 -6.6524 71.3475 Manta Ray
MRTag
species taggingdate deploy_lat deploy_lon
Manta Ray 3/24/2016 -5.4191 71.83855
Manta Ray 02/05/2013 -5.2568 71.65768333
Manta Ray 02/07/2013 -5.33448 71.9812
Manta Ray 02/08/2013 -5.3046 71.94231667
I then used the code below to make a base map
library(ggmap)
MR_bbox <- make_bbox(lon = MR$Longitude, lat = MR$Latitude, f=1)
MR_map <- get_map(location = MR_bbox, source = "google", maptype = "satellite")
Then plotted my location data from Mr + MRTag onto the map
MR_plot <-
ggmap(MR_map) +
geom_point(data = MR, mapping = aes(x = Longitude, y = Latitude),
shape = 1, color = "white") +
geom_point(data = MRTag, mapping = aes(x = deploy_lon, y = deploy_lat),
shape = 25, fill = "#00FF00", color = "#00FF00") +
xlab("Longitude") +
ylab("Latitude")
This gave me this plot
I'd like to add a legend for the two shapes to the map but I'm not sure of the best way to do it, and methods so far haven't worked
The solution is actually really simple: just move the relevant aesthetic arguments into the aes().
MR_plot <- ggmap(MR_map) +
geom_point(data = MR, aes(x = Longitude, y = Latitude,
color = 'detect', shape = 'detect', fill = 'detect')) +
geom_point(data = MRTag, aes(x = deploy_lon, y = deploy_lat,
color = 'tag', shape = 'tag', fill = 'tag')) +
xlab("Longitude") +
ylab("Latitude") +
scale_color_manual(name = 'legend', values = c(detect = 'white', tag = '#00FF00')) +
scale_fill_manual(name = 'legend', values = c(detect = NA, tag = '#00FF00')) +
scale_shape_manual(name = 'legend', values = c(detect = 1, tag = 25))
It's actually slightly confusing: if you use color= outside the aes(), then you set the actual color of those points and there is no legend because it's purely an aesthetic choice.
If you use color= (or fill= or shape=) inside the aes(), however, what you're doing is defining another variable that controls the color of the points. If you wanted to color those points based on species, for example, your aes() would be: aes(x = Longitude, y = Latitude, color = species). This is same thing: except by passing a single string you set the color variable for all points in that geom_point to a single value.
You then have to use a scale_color_* function (and corresponding functions for fill and shape) to set those color variables to the specific colors you want. By default, each scale defined in the aes() will get it's own legend. But if you name the legends and give them the same name, then they will be combined into one.
My data set denotes the location (lat, long) of bee hives and how many in that location are positive for a parasite.
plotting the locations on a map is fine but I would like to change the colours of the points that have a parasite presence e.g. heading 'Positive' > 0
I have tried the following code but I can't + to a map it tells me it can't add 0 to a plot
myMap + ggplot(honeybee, aes(x= Long, y= Lat)) +
geom_point(aes(colour = cut(Positive, c(-1, 0, 5))), size = 1) +
scale_color_manual( values = c("red", "black"),
name = "Parasite", labels = c("Absent", "Present"))
Essentially I want the above code fitted to a ggmap
I am not sure where you get your map, since you did not include the data, but here's how you could do it with ggmap. There's no need to call ggplot again. Just include your honeybee datasource directly in the layer
library(ggmap)
m <- get_map("New York City", zoom=14,maptype="toner",source="stamen")
myMap <- ggmap(m)
honeybee <- data.frame(Lat=runif(20,min=40.69, max=40.73),
Long=runif(20, min=-74.03, max=-73.98),
Positive = rnorm(20))
myMap +
geom_point(data=honeybee,
mapping=aes(x= Long, y= Lat, colour = Positive>0),
size = 5) +
scale_color_manual( values = c("red", "yellow"),
name = "Parasite",
labels = c("Absent", "Present"))
Which produces