Plotting Heatmap with geom_raster in ggmap - r

I have a data frame containing longitude, latitude and a intensity variable (var1.pred).
I would like to plot a smooth filled contour plot on a ggmap map. I have done it using a geom_tile plot but it doesn't look smooth. I have decreased the tile sizes but the plot takes up to much storage. What I want to do is use geom_raster to plot a nice clean contour plot over the map object.
Using the bellow code I have done it using ggplot:
raster <- ggplot(idw.output, aes(x = lon, y = lat, z = var1.pred))+
geom_raster(aes(fill = var1.pred), alpha = 0.5) +
scale_fill_gradient(low = "white", high = "blue")+
geom_contour(colour = "white", binwidth = 1) +
labs(fill = "Frequency", title = "Frequency per area", x = 'Longitude', y = 'Latitude')
raster
This returns the plot:
However I cannot work out how to combine this with a ggmap object. I have tried various things such as:
ggmap(fr) + #fr is a map from get_map
ggplot(idw.output, aes(x = lon, y = lat, z = var1.pred))+
geom_raster(aes(fill = var1.pred), alpha = 0.5) +
scale_fill_gradient(low = "white", high = "blue")+
geom_contour(colour = "white", binwidth = 1) +
labs(fill = "Frequency", title = "Frequency per area", x = 'Longitude', y = 'Latitude')
But I get the error:
Error: Don't know how to add o to a plot
I know the issue has something to do with combining a ggplot and ggmap object but I cannot work out how to get it to work. Any help would be appreciated.
Thanks,
Robin

Without a reproducible example, it is impossible to test your code, but it is likely that you can move the ggplot call to the base_layer argument so that you can keep adding geoms.
ggmap(fr, base_layer = ggplot(idw.output, aes(x = lon, y = lat, z = var1.pred))) +
geom_raster(aes(fill = var1.pred), alpha = 0.5) +
scale_fill_gradient(low = "white", high = "blue")+
geom_contour(colour = "white", binwidth = 1) +
labs(fill = "Frequency", title = "Frequency per area", x = 'Longitude', y = 'Latitude')

Related

How do I add a legend using aes, ggplot2 and maps?

I'm trying to make a map with points plotted for the Canadian prairie provinces, but I'm having no luck adding in a legend to my map. I'm very new to mapping in r, so I'm not understanding how I should include aes to get a legend. My data for siteDataTrees is from an excel csv file and the top looks like this:
siteDataTrees
and the data for siteDataBoth is also from a csv file and the top looks like this:
siteDataBoth.
Here's what I have so far for my code:
library(maps)
library(ggplot2)
library(sf)
prairies1 <- map("worldHires","Canada", xlim = c(-120,-87), ylim = c(49,61),
plot = FALSE, fill = TRUE)
prairies <- st_as_sf(prairies1)
ggplot(data = prairies) +
geom_sf() +
geom_point(data = siteDataTrees, aes(x = long, y = lat), size = 2.5, pch = 21,
fill = "purple", show.legend = TRUE) +
geom_point(data = siteDataBoth, aes(x = long, y = lat), size = 2.5, pch = 21,
fill = "light green", show.legend = TRUE) +
geom_text(data = locations, aes(x = long, y = lat, label = name),
size = 2, col = "black", check_overlap = FALSE) +
annotation_scale(location = "tr", width_hint = 0.2) +
ggtitle("Climate Stations and Tree Chronology Locations for South AB") +
labs(x = "latitude", y = "longitude") +
theme(legend.position = "right") +
coord_sf(xlim = c(-115, -110), ylim = c(48.9, 50.49), expand = FALSE)
I've also included a map to show what it looks like without the legend.
How should I take the data frame prairies and use it with aes to include a legend? Is there another way to add in a legend in ggplot2 without using the aes function? Thank you in advance for your help and please let me know if something is missing as this is my first posting
Let me give you a couple of examples on how to work out a legend using a slightly modified example from r-spatial.
First we prepare the data:
library(maps)
library(ggplot2)
library(sf)
library(rnaturalearth)
library(rnaturalearthdata)
world <- ne_countries(scale = "medium", returnclass = "sf")
(sites <- data.frame(longitude = c(-80.144005, -80.109),
latitude = c(26.479005,26.83),
type = c("tree", "station")))
Now we plot. Case 1: color is not an issue
ggplot(data = world) +
geom_sf() +
geom_point(data = sites,
aes(x = longitude, y = latitude, fill = type),
size = 4,
shape = 23) +
coord_sf(xlim = c(-88, -78), ylim = c(24.5, 33), expand = FALSE) +
theme(legend.position = "bottom")
Case 2: fill color is an issue.
Here we can use a named vectors to pass the colors and the labels we want by type of point. For example:
mapfill <- c('tree' = "forestgreen", 'station' = "purple")
maplab <- c('tree' = "trees in prairies", 'station' = "Stations in prairies")
Then we plot combining both mapfill and maplab:
ggplot(data = world) +
geom_sf() +
geom_point(data = sites, aes(x = longitude, y = latitude, fill = type), size = 4,
shape = 23) +
scale_fill_manual(values = mapfill, labels = maplab) +
coord_sf(xlim = c(-88, -78), ylim = c(24.5, 33), expand = FALSE) +
theme(legend.position = "bottom")
Remark 1 If you do not want type in the legend title you can either delete it using legend. title = element_blank() within theme
Remark 2 If, instead of fill, you are using color, use function scale_color_manual. If you are combining both fill and color do the same with scale_***_manual
In spirit of full disclosure, if you do not mind the colors and you want a quick fix (and I cannot stress this enough) you can also code fill = "TextYouWantInLegend" within aes. See following example:
ggplot(data = world) +
geom_sf() +
geom_point(data = sites[1,], aes(x = longitude, y = latitude, fill = "toto"), size = 4,
shape = 23) +
geom_point(data = sites[2,], aes(x = longitude, y = latitude, fill = "koko"), size = 4,
shape = 23) +
coord_sf(xlim = c(-88, -78), ylim = c(24.5, 33), expand = FALSE) +
theme(legend.position = "bottom")

ggplot2 + geom_point + bubble proportional to size (error "Discrete value supplied to continuous scale")

I am trying to represent dots/bubble corresponding to cities that increase size proportional to population.
despite several attempts, I get always the same error ("Discrete value supplied to continuous scale"), even though my variable is numeric.
Example Data used can be found here
https://github.com/Lulliter/r-ggplot-points-question
Brazil_bound_sf = boundary
Brazil_cit_longlat = list of cities with Population # over few years
Plot does not Work
ggplot() +
geom_sf (data = Brazil_bound_sf,
aes(fill = NULL), alpha = .1,colour = "darkgrey",size = 0.3) +
geom_point(data = Brazil_cit_longlat, aes( x = lon, y = lat, size =
"2016"), fill = "red", color = "grey", alpha = .2) +
scale_size_continuous() +
coord_sf(crs = st_crs(Brazil_bound_sf), datum = NA) +
theme_void()
# Error: Discrete value supplied to continuous scale
Thanks!
This worked for me (I simply replaced "2016" with 2016. This way you are referring to the column in the data frame and not to the string "2016":
ggplot() +
geom_sf (data = x,
aes(fill = NULL), alpha = .1,colour = "darkgrey",size = 0.3) +
geom_point(data = y, aes( x = lon, y = lat, size =
`2016`), fill = "red", color = "grey", alpha = .2) +
scale_size_continuous() +
sf::plot_sf(crs = st_crs(x), datum = NA)

Q: facet_wrap scales per tile

i have two type of parameters and one response for one chemical compound:
The code used to generated this picture was
for (i in levels(data$ProteinName))
{
temp <- subset(data, data$ProteinName == i)
plot <- ggplot(data = temp, aes(x= temp$id, y = temp$Matrix))+
geom_tile( aes( fill= temp$TotalArea))+
labs(title= i, x = NULL, y = NULL, fill = "Average Total Area")+
geom_text(aes(label=round(TotalArea, digits = 0)), color = "White")+
scale_fill_gradientn (colors=c(low = "blue4", mid="gold", high = "red"),
na.value = "violetred")+
theme_bw()
print(plot)
}
but this is one of 12 plots so for my report i had to take it into a facet but i haven't found anny method to create a free scale for the "z axis" scale the current code is
temp <- data
plot <- ggplot(data = temp, aes(x= temp$id, y = temp$Matrix))+
facet_wrap(~temp$ProteinName, scale = "free")+
geom_tile( aes( fill= temp$TotalArea))+
labs(title= i, x = NULL, y = NULL, fill = "Average Total Area")+
geom_text(aes(label=round(TotalArea, digits = 0)), color = "White")+
scale_fill_gradientn (colors=c(low = "blue4", mid="gold", high = "red"),
na.value = "violetred")+
theme_bw()
print(plot)
and gives the follow:
but here is the color of the tiles (z axis) not free did any body know how to create a free z axis?
you can see ad the PE facet that it is only blue but within this facet there is a quite large difference with the observed concentration.
The goal is that te readers can see what is the larges respons (red) and the lowest (blue).
Hopefully you can help me.
Thanks for the answers,
with the help of the post:
Place a legend for each facet_wrap grid in ggplot2
it was verry easy done,
the old script was:
for (i in levels(data$ProteinName))
{
temp <- subset(data, data$ProteinName == i)
plot <- ggplot(data = temp, aes(x= temp$id, y = temp$Matrix))+
geom_tile( aes( fill= temp$TotalArea))+
labs(title= i, x = NULL, y = NULL, fill = "Average Total Area")+
geom_text(aes(label=round(TotalArea, digits = 0)), color = "White")+
scale_fill_gradientn (colors=c(low = "blue4", mid="gold", high = "red"),
na.value = "violetred")+
theme_bw()
print(plot)
}
with result:
old plot
after that we updated the script with the fucntion grid.arrange(grobs = list_of_plots) from the gridextra package
there for i had to make a list in the loop, this was done with: plot_v[[i]] <- plot, plot_v is the name of the list of plots.
this list was then added to the grid arrange
so the new script is now
require(gridExtra)
require(ggplot2)
plot_v <- list()
for (i in levels(data$ProteinName))
{
temp <- subset(data, data$ProteinName == i)
plot <- ggplot(data = temp, aes(x= temp$id, y = temp$Matrix))+
geom_tile( aes( fill= temp$TotalArea))+
labs(title= i, x = NULL, y = NULL, fill = "Average Total Area")+
geom_text(aes(label=round(TotalArea, digits = 0)), color = "White", size= 2.5)+
scale_fill_gradientn (colors=c(low = "blue4", mid="gold", high = "red"),
na.value = "violetred")+
theme_bw()+
guides(fill = "none")
print(plot)
assign(paste("plot", i, sep="_"), plot)
plot_v[[i]] <- plot
}
grid.arrange(grobs = plot_v)
this gives as result
new plot
I want to thank you for your help

How to take the actual contour fill in a ggmap

I am new in R and I want to plot a map with the distribution/ contour of pollutants and I have trouble doing that.
I a sample of my dataset is:
> head(noxco2_contour)
latitude longitude NOX.CO2
1 52.45060 -1.933200 0.01240829
2 52.45061 -1.933198 0.01045806
3 52.45060 -1.933207 0.01235869
4 52.45059 -1.933202 0.01083601
5 52.45059 -1.933199 0.01243808
6 52.45058 -1.933207 0.01379813
After getting the needed map with ggmap, I'm trying to overplot filled contours of NOX.CO2. and I am using this code:
`ggmap(west_midlands, extent = "panel") + geom_density2d(data = noxco2_contour, aes(x = longitude, y = latitude, z=NOX.CO2), size = 0.3, contour=T) +
stat_density2d(data = noxco2_contour,
aes(x = longitude, y = latitude, z= NOX.CO2, fill = ..level.., alpha = ..level..), size = 0.05,
geom = "polygon") + scale_fill_gradient(low = "green", high = "red") +
scale_alpha(range = c(0, 1), guide = FALSE)
However I am getting the warning message of: ' Warning: Ignoring unknown aesthetics: z' and practically the fill is NOT the real values of the NOX.CO2 but a level OF unknown value/matterial. the image that i get is1 which is not the correct one.
I have checked the following relevant links Filled contour plot with R/ggplot/ggmap 3 but I get different errors and still not the correct fill.
When using:
ggmap(west_midlands, extent = "panel") + geom_density2d(data = noxco2_contour, aes(x = longitude, y = latitude), size = 0.3) +
+ stat_density2d(data = noxco2_contour,
+ aes(x = longitude, y = latitude, group= NOX.CO2, colour= NOX.CO2), size = 0.05,
+ geom = "polygon") + scale_fill_gradient(low = "green", high = "red") +
+ scale_alpha(range = c(0, 1), guide = FALSE)
I get the following: Computation failed in stat_density2d():
missing value where TRUE/FALSE needed
When I am using this code
`ggmap( west_midlands, extent = "panel" ) +
+ stat_contour(data = noxco2_contour, geom="contour", bins=20,
+ aes(x = longitude, y = latitude, z = NOX.CO2, fill = ..level.. ) ) +
+ scale_fill_continuous(name = "NOx(ppb)/CO2(ppm)", low = "yellow", high = "red" )
I am getting this Computation failed instat_contour():
Contour requires singlezat each combination ofxandy`.
I really appreciate any help
Many thanks,
Bill

Legend units for geom_point size

I have used geom_point in ggplot2 to display values as the area of each point:
geom_point(aes(size = sqrt(z/pi))
However, the legend units are the transformed values, is it possible to have the legend display the original values alongside their respective bubble size?
Edit: sorry I should have provided more information to begin with
library(ggplot2)
data <- data.frame(x = sample(1:10), y = sample(1:10), z = sample(1:10), colour = c("red", "yellow", "green","pink","black","brown","grey","white","purple","beige"))
ggplot(data, aes(x = x, y = y)) + geom_point(aes(size = sqrt(z/pi)), pch = 21) + aes(fill = colour) + scale_fill_brewer(palette = "set1")
Try adding:
+scale_colour_manual(guide = guide_legend(override.aes=aes(size=values)))

Resources