ggmap extended zoom or boundaries - r

I am trying to fix the following problem.
I use ggplot2 to plot a map of an island:
island = get_map(location = c(lon = -63.247593, lat = 17.631598), zoom = 14, maptype = "satellite")
islandMap = ggmap(island, extent = "panel", legend = "bottomright")
RL = geom_point(aes(x = longitude, y = latitude), data = data, size = 4, color = "#ff0000")
islandMap + RL
Coordinates of the RL points:
data = data.frame(
ID = as.numeric(c(1:8)),
longitude = as.numeric(c(-63.27462, -63.26499, -63.25658, -63.2519, -63.2311, -63.2175, -63.23623, -63.25958)),
latitude = as.numeric(c(17.6328, 17.64614, 17.64755, 17.64632, 17.64888, 17.63113, 17.61252, 17.62463))
)
Now the problem is that when I use zoom = 13 the island is too small in the plot and when I use zoom = 14 it is perfectly centered. But when I plot the RL points, two get cut off because its too much to the East and the other one too much to the West. I looked some solutions up like the following one, using a boundary box. However, I am bound to using satellite imagery, so bound to Google, which doesn't support the boundary box solution.
lon = data$longitude
lat = data$latitude
box = make_bbox(lon, lat, f = 0.1)
island = get_map(location = box, zoom = 14, source = "osm")
islandMap = ggmap(island, extent = "panel", legend = "bottomright")
RL = geom_point(aes(x = longitude, y = latitude), data = data, size = 4, color = "#ff0000")
islandMap + RL
How can I make sure that the map is as big as using zoom = 14, all the points are within the plot (plus a margin around this) and satellite imagery?

Using my answer from this question, I did the following. You may want to get a map with zoom = 13, and then you want to trim the map with scale_x_continuous() and scale_y_continuous().
library(ggmap)
library(ggplot2)
island = get_map(location = c(lon = -63.247593, lat = 17.631598), zoom = 13, maptype = "satellite")
RL <- read.table(text = "1 17.6328 -63.27462
2 17.64614 -63.26499
3 17.64755 -63.25658
4 17.64632 -63.2519
5 17.64888 -63.2311
6 17.63113 -63.2175
7 17.61252 -63.23623
8 17.62463 -63.25958", header = F)
RL <- setNames(RL, c("ID", "Latitude", "Longitude"))
ggmap(island, extent = "panel", legend = "bottomright") +
geom_point(aes(x = Longitude, y = Latitude), data = RL, size = 4, color = "#ff0000") +
scale_x_continuous(limits = c(-63.280, -63.20), expand = c(0, 0)) +
scale_y_continuous(limits = c(17.60, 17.66), expand = c(0, 0))

Related

Mark the center of state in stamen maps

I want to draw a map like the below picture of untitled state and show the center of all state by a colorful circle.
There is google map API which can use in R.But it seems that it's no longer available to use free of charge.
How can I draw this picture by Stamn Maps library in R?
If there is a good tutorial about Stamn Maps, I'll appreciate any helps.
thanks for your answers I find one of the solutions that shows map in r by Stamn Maps
d <- data.frame(lat = state.center$y,
lon = state.center$x)
#-128.5, 27.5, -69, 49
US <- get_stamenmap(bbox = c(left = -128.5, bottom = 27.5, right =
-68, top = 50) ,zoom = 4, maptype = c("terrain",
"terrain-background", "terrain-labels", "terrain-lines", "toner",
"toner-2010", "toner-2011", "toner-background", "toner-hybrid",
"toner-labels", "toner-lines", "toner-lite", "watercolor"),
crop = TRUE, messaging = FALSE, urlonly = FALSE,
color = c("color", "bw"), force = FALSE, where = tempdir())
p <- ggmap(US, base_layer = ggplot(data = d)) +
geom_point(aes(x = lon, y = lat), color = "blue", size = 2, alpha = 0.5)
p
A minimal example to kickstart your journey:
set.seed(1702)
points <- data.frame(lon = rnorm(10, -95.4, 0.1),
lat = rnorm(10, 29.7, 0.1))
# get_stamenmap() defaults to the map of Houston, TX if there
# is no boundary box defined in the form of:
# c(lon_min, lat_min, lon_max, lat_max)
# For more information see ?get_stamenmap
ggmap(get_stamenmap()) +
geom_point(data = points,
aes(lon, lat),
color = "red")

How to zoom in to the north east area of US in R (ggplot/ggmap) with limit (xlim and ylim)?

I was working on a project where I want to use ggplot or ggmap to show 'only' the northeast part of the US (we can use NYC as our center).
I locate the x and y of NY state and want to create the range for both axis +/- 10 degree, but did not know how to make the ggmap only shows the area i want it to show. I kept getting either the whole map or only a point...please help...thank you!!!
which(usa1$stateName == "new york")
ny.x = usa1$x[which(usa1$stateName=="new york")]
ny.y = usa1$y[which(usa1$stateName=="new york")]
ny.x1 = xlim(ny.x -10, ny.x+10)
ny.y1 = ylim(ny.y -10, ny.y+10)
us.map.zm <- ggplot(usa1, aes(map_id = stateName))
us.map.zm <- us.map.zm + geom_map(map =usa, aes(fill = usa1$Murder),fill="white",color ="black") + ylim(ny.y-10, ny.y+10) + xlim(ny.x-10,ny.x+10)
us.map.zm <- us.map.zm + geom_point(data=usa1,aes(x = usa1$x, y = usa1$y,size=usa1$POP17, color="blue"))
us.map.zm <- us.map.zm + coord_map() + ggtitle("Northeast US Populaton vs Murder rate")
us.map.zm
Add the latitude and longitude limit
lat <- c(23.49, 34.5)
lon <- c(12.33, 21.36)
### Get a map
map <- get_map(location = c(lon = mean(lon), lat = mean(lat)), zoom = 12,
maptype = "satellite", source = "google")
### When you draw a figure, you limit lon and lat.
us.map.zm <- ggmap(map)+
scale_x_continuous(limits = c(11.33, 11.36), expand = c(0, 0)) +
scale_y_continuous(limits = c(44.49, 44.5), expand = c(0, 0))
Alter and use this as you per your requirements

r ggmap - add annotation superimposed on map

Questions about map legend editing exist (e.g.), but not exactly what I need.
Using ggmap, how do I select points in a map and add annotations superimposed on the map? Take the following code:
Map <- get_map(location = 'Santiago, Chile', zoom = 6, maptype = "terrain")
Map <- ggmap(Map)
Points <- data.frame(lon=c(-71.82718,-71.31263),lat=c(-34.36935,-34.29322))
Map_Points <- Map + geom_point(data = Points,aes(x=lon,y=lat,size=6))
So now I have a nice map with a few points. How do I write some annotation near one of the points?
Quite straightforward:
Code
library(ggrepel) # for the auto-repelling label
Map +
geom_point(data = Points,
aes(x = lon, y = lat),
size = 3) +
geom_label_repel(data = Points,
aes(x = lon, y = lat, label = name),
size = 3,
vjust = -2,
hjust = 1)
Data
library(tmaptools) # for the geocode lookup
library(ggmap)
santiago_coords <- rbind(as.numeric(paste(geocode_OSM("Santiago, Chile")$coords)))
Map <- get_map(location = santiago_coords, zoom = 6, maptype = "terrain")
Map <- ggmap(Map)
Points <- data.frame(lon=c(-71.82718,-71.31263),
lat=c(-34.36935,-34.29322),
name=c("Location One", "Location Two"))

Display all latitude and longitude once in a MAP

I have a dataset like
latitude longitude Class prediction
9.7 21.757 244732 1
12.21 36.736 112206 0
-15.966 126.844 133969 1
Now i am trying to group all '1' at prediction column and take their latitude and longitude, later i want to display the all points on a single map.
Actually the code i wrote its takes each '1' on prediction column and takes lat and long respectively and display one point on map each time. But I want to collect all lat and long where prediction is 1 and display all points on a one map.
library(ggplot2)
library(ggmap) #install.packages("ggmap")
#data set name testData1
for (i in 1:100){
if (testData1$prediction[i]==1) {
lat <- testData1$latitude[i]
lon <- testData1$longitude[i]
df <- as.data.frame(cbind(lon,lat))
# getting the map
mapgilbert <- get_map(location = c(lon = mean(df$lon), lat = mean(df$lat)), zoom = 4,
maptype = "satellite", scale = 2)
# plotting the map with some points on it
ggmap(mapgilbert) +
geom_point(data = df, aes(x = lon, y = lat, fill = "red", alpha = 0.8), size = 5, shape = 21) +
guides(fill=FALSE, alpha=FALSE, size=FALSE)
}
}
I think you're overcomplicating things. You could simply subset df like so:
ggmap(mapgilbert) +
geom_point(data = subset(df, prediction == 1), aes(x = lon, y = lat, fill = "red", alpha = 0.8), size = 5, shape = 21) +
guides(fill = FALSE, alpha = FALSE, size = FALSE)

Plot circle with a certain radius around point on a map in ggplot2

I have a map with the 8 points plotted on it:
library(ggplot2)
library(ggmap)
data = data.frame(
ID = as.numeric(c(1:8)),
longitude = as.numeric(c(-63.27462, -63.26499, -63.25658, -63.2519, -63.2311, -63.2175, -63.23623, -63.25958)),
latitude = as.numeric(c(17.6328, 17.64614, 17.64755, 17.64632, 17.64888, 17.63113, 17.61252, 17.62463))
)
island = get_map(location = c(lon = -63.247593, lat = 17.631598), zoom = 13, maptype = "satellite")
islandMap = ggmap(island, extent = "panel", legend = "bottomright")
RL = geom_point(aes(x = longitude, y = latitude), data = data, color = "#ff0000")
islandMap + RL + scale_x_continuous(limits = c(-63.280, -63.21), expand = c(0, 0)) + scale_y_continuous(limits = c(17.605, 17.66), expand = c(0, 0))
Now I want to plot a circle around each of the 8 plotted locations. The circle has to have a radius of 450 meters.
This is what I mean, but then using ggplot: https://gis.stackexchange.com/questions/119736/ggmap-create-circle-symbol-where-radius-represents-distance-miles-or-km
How can I achieve this?
If you only work on a small area of the earth, here is a approximation. Each degree of the latitude represents 40075 / 360 kilometers. Each degrees of longitude represents (40075 / 360) * cos(latitude) kilomemters. With this, we can calculate approximately a data frame including all points on circles, knowing the circle centers and radius.
library(ggplot2)
library(ggmap)
data = data.frame(
ID = as.numeric(c(1:8)),
longitude = as.numeric(c(-63.27462, -63.26499, -63.25658, -63.2519, -63.2311, -63.2175, -63.23623, -63.25958)),
latitude = as.numeric(c(17.6328, 17.64614, 17.64755, 17.64632, 17.64888, 17.63113, 17.61252, 17.62463))
)
#################################################################################
# create circles data frame from the centers data frame
make_circles <- function(centers, radius, nPoints = 100){
# centers: the data frame of centers with ID
# radius: radius measured in kilometer
#
meanLat <- mean(centers$latitude)
# length per longitude changes with lattitude, so need correction
radiusLon <- radius /111 / cos(meanLat/57.3)
radiusLat <- radius / 111
circleDF <- data.frame(ID = rep(centers$ID, each = nPoints))
angle <- seq(0,2*pi,length.out = nPoints)
circleDF$lon <- unlist(lapply(centers$longitude, function(x) x + radiusLon * cos(angle)))
circleDF$lat <- unlist(lapply(centers$latitude, function(x) x + radiusLat * sin(angle)))
return(circleDF)
}
# here is the data frame for all circles
myCircles <- make_circles(data, 0.45)
##################################################################################
island = get_map(location = c(lon = -63.247593, lat = 17.631598), zoom = 13, maptype = "satellite")
islandMap = ggmap(island, extent = "panel", legend = "bottomright")
RL = geom_point(aes(x = longitude, y = latitude), data = data, color = "#ff0000")
islandMap + RL +
scale_x_continuous(limits = c(-63.280, -63.21), expand = c(0, 0)) +
scale_y_continuous(limits = c(17.605, 17.66), expand = c(0, 0)) +
########### add circles
geom_polygon(data = myCircles, aes(lon, lat, group = ID), color = "red", alpha = 0)
Well, as the referred posting already suggests - switch to a projection that is based in meters, and then back:
library(rgeos)
library(sp)
d <- SpatialPointsDataFrame(coords = data[, -1],
data = data,
proj4string = CRS("+init=epsg:4326"))
d_mrc <- spTransform(d, CRS("+proj=merc +a=6378137 +b=6378137 +lat_ts=0.0 +lon_0=0.0 +x_0=0.0 +y_0=0 +k=1.0 +units=m +nadgrids=#null +no_defs"))
Now, the width can be specified in meters:
d_mrc_bff_mrc <- gBuffer(d_mrc, byid = TRUE, width = 450)
Transform it back and add it to the plot using geom_path:
d_mrc_bff <- spTransform(d_mrc_bff_mrc, CRS("+init=epsg:4326"))
d_mrc_bff_fort <- fortify(d_mrc_bff)
islandMap +
RL +
geom_path(data=d_mrc_bff_fort, aes(long, lat, group=group), color="red") +
scale_x_continuous(limits = c(-63.280, -63.21), expand = c(0, 0)) +
scale_y_continuous(limits = c(17.605, 17.66), expand = c(0, 0))
Calculating distance in km given latitude and longitude isn't super straightforward; 1 degree lat/long is a greater distance at the equator than at the poles, for example. If you want an easy workaround that you can eyeball for accuracy, you might try:
islandMap + RL +
scale_x_continuous(limits = c(-63.280, -63.21), expand = c(0, 0)) +
scale_y_continuous(limits = c(17.605, 17.66), expand = c(0, 0)) +
geom_point(aes(x = longitude, y = latitude), data = data, size = 20, shape = 1, color = "#ff0000")
You'll need to adjust the size paramter in the 2nd geom_point to get closer to what you want. I hope that helps!
An accurate solution is using the geosphere::destPoint() function. This works without switching projections.
Define function to determine 360 points with a certain radius around one point:
library(dplyr)
library(geosphere)
fn_circle <- function(id1, lon1, lat1, radius){
data.frame(ID = id1, degree = 1:360) %>%
rowwise() %>%
mutate(lon = destPoint(c(lon1, lat1), degree, radius)[1]) %>%
mutate(lat = destPoint(c(lon1, lat1), degree, radius)[2])
}
Apply function to each row of data and convert to data.frame:
circle <- apply(data, 1, function(x) fn_circle(x[1], x[2], x[3], 450))
circle <- do.call(rbind, circle)
Then the map can be easily obtained by:
islandMap +
RL +
scale_x_continuous(limits = c(-63.280, -63.21), expand = c(0, 0)) +
scale_y_continuous(limits = c(17.605, 17.66), expand = c(0, 0)) +
geom_polygon(data = circle, aes(lon, lat, group = ID), color = "red", alpha = 0)
A solution using st_buffer() from the sf package.
library(ggmap)
library(ggplot2)
library(sf)
data <- data.frame(
ID = 1:8,
longitude = c(-63.27462, -63.26499, -63.25658, -63.2519,
-63.2311, -63.2175, -63.23623, -63.25958),
latitude = c(17.6328, 17.64614, 17.64755, 17.64632,
17.64888, 17.63113, 17.61252, 17.62463)
)
Convert data.frame to sf object:
points_sf <- sf::st_as_sf(data, coords = c("longitude", "latitude"), crs = 4326)
For this example we use UTM zone 20, which contains the coordinates of the island:
data_sf_utm <- sf::st_transform(points_sf, "+proj=utm +zone=20")
Now we can buffer the point by 450 meters:
circle <- sf::st_buffer(data_sf_utm, dist = 450)
ggmap seems to have some issues with geom_sf. Setting inherit.aes to FALSE returns the desired map.
island <- ggmap::get_map(location = c(lon = -63.247593, lat = 17.631598), zoom = 14, maptype = "satellite")
ggmap(island, extent = "panel", legend = "bottomright") +
geom_sf(data = points_sf, color = "red", inherit.aes = FALSE) +
geom_sf(data = circle, color = "red", alpha = 0, inherit.aes = FALSE)
Created on 2020-10-11 by the reprex package (v0.3.0)

Resources