Add legend to ggmap - r

I am trying to add a legend to a plot generated by ggmap package in R. The dataset I am working with is
Latitude Longitude amount
61.37072 -152.40442 436774
32.80667 -86.79113 3921030
34.96970 -92.37312 1115087
33.72976 -111.43122 5068957
The code I am using is
library(ggplot2)
library(ggmap)
MyMap <- get_map(location = c(lon = -96.5, lat = 40.68925), zoom = 4,maptype = "terrain", scale = 2)
ggmap(MyMap)+
geom_point(data = data,aes(x = Longitude , y = Latitude ),size=sqrt(data$amount)/800,col='darkred', shape = 19,alpha = .5)
Now I want to add legend to this plot. The legend should show the sizes of the circles on the map correspond to certain amount. How can I do it?

The size argument should be included within the aes() section of the geom_point function, as follows:
plot <- ggmap(MyMap) +
geom_point(data = data,aes(x = Longitude , y = Latitude, size=amount), col='darkred', shape = 19,alpha = .5)
plot
If you want to have further customisation of the scale, you can use the optional argument scale_size_area() to choose the breaks and labels for the legend. For example:
plot + scale_size_area(breaks = c(436774, 1115087, 4000000, 5068957),
labels = c("436774", "1115087", "4000000", "5068957"))
Change Point Size:
If you want to adjust the size of the points, you are better off using the scale_size function, which lets you specify a range:
plot + scale_size(range = c(5,9))

Related

Make Raster Fill Extent of Plot with ggplot

I have a raster layer that is larger than my plotting area. I'd like to plot a smaller section of the raster (and other layers), so I'd like to set the plotting area using xlim() and ylim() in ggplot.
However, setting the plotting area in that way clips the raster to the exact xlim and ylim, instead of the actual extent of the plot. That leaves an ugly border around the raster, but none of the other layers. Is there a better way to set the limits of a plot so that the raster isn't cut off?
Here's an example:
library(USAboundaries)
library(elevatr)
library(tidyverse)
states <- us_states(states = c("AL", "FL", "GA", "SC"))
se.elevations <- get_elev_raster(locations = states, z = 7, clip = "locations")
se.elevation.df <- raster::as.data.frame(se.elevations, xy = TRUE) %>%
rename(elevation = 3) %>%
na.omit() %>%
filter(elevation >= 0)
xlimit <- c(-87, -80)
ylimit <- c(29, 34)
ggplot()+
geom_tile(data = se.elevation.df, aes(x = x, y = y, fill = elevation))+
scale_fill_gradientn(colours= c("gray", "black"))+
geom_sf(data = states, fill = NA)+
xlim(xlimit)+
ylim(ylimit)
As you can see, the raster is cut off, but the states continue to the edge of the plot. Ugly!
As a general rule, if you want to zoom on a part of your plot set the limits via the coord, i.e. in your case coord_sf:
library(ggplot2)
ggplot()+
geom_tile(data = se.elevation.df, aes(x = x, y = y, fill = elevation))+
scale_fill_gradientn(colours= c("gray", "black"))+
geom_sf(data = states, fill = NA)+
coord_sf(xlim = xlimit, ylim = ylimit)

How can I plot points (plot a ggplot for example) onto a Tanakaplot?

I am attempting to create a map for my PhD of some sampling locations in the rainforest, and I thought it would be cool to represent their elevation on the map as well, since it can be significant.
After much experimentation with plotting my points on DEM rasters I decided it is not the most visually clear way of doing it so I thought to turn the raster into a contour and represent it that way. So I found this wonderful tanaka package to create an astonishing contoured elevation map, and it looks great.
However now I run into the problem that I cannot seem to find the way how to plot my sampling points onto the tanaka plot.
I made a nice ggplot to represent the shape and color of the points with their longitude and latitude which would be great if I could integrate it. Is there a way?
Here are my lines for the tanakaplot and the ggplot.
tanaka(park, breaks = seq(25,250,25), legend.pos = "topright",
legend.title = "Elevation\n(meters)",
col = brewer.pal(n = 8, name = "Blues"))
ggplot(data = worldmap) +
geom_sf() +
geom_point(data = necropsies,
aes(x = lng, y = lat, color = anthrax, shape = anthrax), size = 2) +
scale_color_manual(values=c("green", "red")) +
coord_sf(xlim = c(-7.37, -7.255), ylim = c(5.775, 5.89))

ggplot2 (version 3) incompatibility with ggmap for geom_density_2d

ggplot2 version 3 seems to have an incompatibility with ggmap when using the geom_density2d() function to add a layer. The following code returns an error (though worked with ggplot2 version 2):
# Create a data frame
df <- data.frame(
long = rnorm(50, -122.32, .2),
lat = rnorm(50, 47.6, .2)
)
# Use qmplot to create a base layer of map tiles
base_plot <- qmplot(
data = df,
x = long, # data feature for longitude
y = lat, # data feature for latitude
geom = "blank", # don't display data points (yet)
maptype = "toner-background", # map tiles to query
darken = .7, # darken the map tiles
legend = "topleft" # location of legend on page
)
# Show the map in RStudio
base_plot
# Use ggplot to create a 2d density map (without tiles -- works fine)
ggplot(df, aes(x = long, y = lat)) +
geom_density2d() +
stat_density_2d(
aes(x = long, y = lat, fill = stat(level)), # in v2, fill = ..level..
# Use the computed density to set the fill
alpha = .3,
geom="polygon" # Set the alpha (transparency)
)
# Add 2d density plot on map tiles -- returns an error
base_plot +
geom_density2d() +
stat_density_2d(
aes(x = long, y = lat, fill = stat(level)), # in v2, fill = ..level..
# Use the computed density to set the fill
alpha = .3,
geom="polygon" # Set the alpha (transparency)
)
# Error in width_cm(guide$barwidth %||% theme$legend.key.width) :
# Unknown input
Any guidance on how to use geom_density2d() to add a layer to a qmplot() map would be appreciated!
(Map below of the image created with ggplot2 version 2)
Answered in comments via #Tung: the issue is with ggmap, and the solution is to use the development version of ggmap (devtools::install_github("dkahle/ggmap")

Small ggplot2 plots placed on coordinates on a ggmap

I would like to first use ggmap to plot a specific area with longitude and latitude as axes.
Then I would like to put small ggplot2 plots on the specific locations, given their longitude and latitude. These can be barplots with minimal theme.
My database may have the columns:
1. town
2. longitude
3. latitude
4. through 6. value A, B, C
I generate a plot (pseudocode)
p <- ggmap(coordinates)
and I have my minimal ggplot2 design
q<-ggplot2()+geom_bar(....)+ ... x-axis null y axis null minimal template
How to combine the two designs to have a ggmap with small minimal ggplot plots imposed on specific coordinates of the map?
Here's one I did using pie charts as points on a scatterplot. You can use the same concept to put barcharts on a map at specific lat/long coordinates.
R::ggplot2::geom_points: how to swap points with pie charts?
Needs further update. Some of the code used was abbreviated from another answer, which has since been deleted. If you find this answer via a search engine, drop a comment and I'll get around to fleshing it back out.
Updated:
Using mostly your adapted code from your answer, but I had to update a few lines.
p <- ggmap(Poland) + coord_quickmap(xlim = c(13, 25), ylim = c(48.8, 55.5), expand = F)
This change makes a better projection and eliminates the warnings about duplicated scales.
df.grobs <- df %>%
do(subplots = ggplot(., aes(1, value, fill = component)) +
geom_col(position = position_dodge(width = 1),
alpha = 0.75, colour = "white") +
geom_text(aes(label = round(value, 1), group = component),
position = position_dodge(width = 1),
size = 3) +
theme_void()+ guides(fill = F)) %>%
mutate(subgrobs = list(annotation_custom(ggplotGrob(subplots),
x = lon-0.5, y = lat-0.5,
xmax = lon+0.5, ymax = lat+0.5)))
Here I explicitly specified the dodge width for your geom_col so I could match it with geom_text. I used round(value, 1) for the label aesthetic, and it automatically inherits the x and y aesthetics from the subplots = ggplot(...) call. I also manually set the size to be quite small, so the labels would fit, but then I increased the overall bounding box for each subgrob, from 0.35 to 0.5 in each direction.
df.grobs %>%
{p +
.$subgrobs +
geom_text(data=df, aes(label = name), vjust = 3.5, nudge_x = 0.065, size=2) +
geom_col(data = df,
aes(Inf, Inf, fill = component),
colour = "white")}
The only change I made here was for the aesthetics of the "ghost" geom_col. When they were set to 0,0 they weren't plotted at all since that wasn't within the x and y limits. By using Inf,Inf they're plotted at the far upper right corner, which is enough to make them invisible, but still plotted for the legend.

Plotting contours on map using ggmap

I have Particulate Matter concentration difference (After - Before) for Port of Los Angeles area. I am trying to use ggmap to plot concentration contours on map but the result looks way different. The code I used is shown below (and data is below the code):
Code
install.packages('ggmap')
library(ggmap)
PM = read.csv('data.csv', stringsAsFactors = FALSE)
Get Longitude and Latitude
geocode("Port of Los Angeles") # Not centered
geocode("Compton, CA") # Now centered
Use Compton LON and LAT
POLA = c(lon = -118.220071, lat = 33.895849)
POLA.map = get_map(location = POLA, zoom = 10, color = 'bw')
ggmap(POLA.map) + geom_point(data = PM, mapping = aes(Longitude, Latitude)) +
stat_density2d(data = PM, mapping = aes(x = Longitude, y = Latitude, fill=..level..), geom = "polygon", alpha = 0.3, contour = TRUE)
However, the contour plot should have a pattern like this:
https://drive.google.com/file/d/0B3XVjcsci0y3VDBTc01PYkhOckE/view?usp=sharing
ggplot(PM, aes(UTM.X, UTM.Y)) + geom_tile(aes(fill = Value), alpha = 0.8, color = "black") +
scale_fill_gradient(low = 'green', high = 'red')
Data: Col-1: Longitude, Col-2: Latitude, Col-3: UTM-X, Col-4: UTM-Y , Col-5: Values
UTM Coordinates Units: Meters, UTM Zone = 11 N, Datum = WGS84. Data is available here: https://drive.google.com/file/d/0B3XVjcsci0y3LUpudko1S2c1cnc/view?usp=sharing
stat_density2d is used for plotting density maps, for example dark colours where there are lots of points and light colours where there's few. You have a regular grid with a Value attribute, not a density plot.
So you should be using geom_tile to get a regular grid map. But your lat-long coordinates do not form an axis-aligned grid. Try this:
ggplot(data = PM, mapping = aes(x = Longitude, y = Latitude, fill=Value)) + geom_tile()
and you get a blank plot, try this:
ggplot(data = PM, mapping = aes(x = UTM.X, y = UTM.Y, fill=Value)) + geom_tile()
and you get your plot. Of course its not in the same coordinate system as the ggmap background.
You can probably use base R's contourLines function to get the coordinates of contour lines in UTM coordinates, make a SpatialLinesDataFrame, then transform to Lat-long and add to a ggmap.
Another possibility to get what looks like a grid map is to use points with squares as the shape.
ggmap(POLA.map) + geom_point(data = PM, mapping = aes(Longitude, Latitude, colour=Value), size=4, alpha=0.5, shape=15) + scale_colour_gradient(low = 'green', high = 'red')
There's some artefacts where the grid cells overlap that look a bit like cell outlines, and the legend is showing with no opacity so looks more saturated than the cells. You'll have to get the size parameter right, as it depends on the size of your graphics device.
Failing all that, turn your data into a raster package raster object, save it as a GeoTIFF, and load it into QGIS, which can reproject UTM grids onto Lat-long on the fly.
QGIS also has some nice blending modes so you can do this pretty easily:
Note this is not transparency, this is multiplicative blending. Transparency causes dark colours to get washed out, whereas multiplicative blending lets black show through, so labelling and base map detail are still visible.
Also, note how the raster is not axis-aligned (especially obvious at the bottom).

Resources