How can I plot GPS trajectory over road and zoom on that road?
Can someone please take a point (40.74640013950355, -73.98755303328286, in Manhattan) and plot it over the corresponding road network [may be a grid 600ft by 600ft]. Please edit the code below to illustrate -
lat <- 40.74640013950355
long <- -73.98755303328286
tbl <- tibble(lat, long)
ggplot(data = tbl,
aes(x = lat,
y = long)) +
geom_point()
Once I know how to plot the road and I can overlay my trajectory data by modifying tbl above.
Thanks
There is no big difficulty to achieve such plot, starting from the example given in tigris library:
library(tigris)
library(ggplot2)
library(ggthemes)
roads <- roads("Maine", "031")
gg <- ggplot() + geom_sf(data = roads, color="black", fill="white", size=0.25) + theme_map()
lat <- 43.5; long <- -70.6; bbox = 0.02
bbox_gg = coord_sf(xlim=c(long-bbox/2, long+bbox/2), ylim=c(lat-bbox/2, lat+bbox/2))
gg + geom_point(data=data.frame(lat, long), aes(x=long, y=lat), size=4, color="red") + bbox_gg
What is done here is just adding a geom_point() aesthetic on top of the geom_sf() layer. We can use a kind of bounding box coordinate limit to adjust the zoom
EDIT
If you need some road names on your map, you can add this to the plot:
geom_sf_label(data=subset(roads, roads$RTTYP!="M"), aes(label=FULLNAME))
here I use subset to avoid plotting all little road names. Eventually, you might want to find a way to zoom/subset your data before plotting, because it's gonna be too long to do it like this.
Related
I'm trying to display labels on GIS polygon features in R using the st_centroid function in the sf library. Unfortunately, while the head() function seems to show that each polygon has different x and y coordinates associated with it, all labels get rendered overlapping at a single point on the map (which is apparently the centroid of one particular polygon). What am I doing wrong here?
Current code setup:
library("ggplot2")
library("sf")
sf::sf_use_s2(FALSE) #makes centroids not break
world <- st_read("C:/prgrm/gis/source/10m_land_and_islands.shp")
prov <- st_read("C:/prgrm/gis/edited ncm/ncm_provinces.shp")
prov <- cbind(prov, st_coordinates(st_centroid(prov))) #attaches centroids to 'prov' dataset
head(prov)
ggplot(data = world) +
geom_sf() +
geom_sf(data=prov, aes(fill="blue")) +
geom_text(data=prov, aes(X,Y, label=provname_r), size=5) +
coord_sf(xlim=c(-2000000,1000000),ylim=c(-1500000, 3000000), crs=st_crs(3310))
You may be better off with specifying the centroid placement via fun.geometry argument of the geom_sf_text() call / by the way the default is sf::st_point_on_surface() - which is a good default as it makes sure that the label is not placed inside a hole, should the polygon have one.
Consider this example, using the well known & much loved nc.shp shapefile that ships with {sf}.
library(sf)
library(ggplot2)
# in place of your world dataset
shape <- st_read(system.file("shape/nc.shp", package="sf")) # included with sf package
# in place of your prov dataset
ashe <- shape[1, ]
ggplot(data = shape) +
geom_sf() +
geom_sf(data = ashe, fill = "blue") +
geom_sf_text(data = ashe,
aes(label = NAME),
color = "red",
fun.geometry = st_centroid)
I want to generate 12 maps using ggplot and facet_wrap which illustrate ocean temperature across the Scotian shelf from Jan-Dec. I was given a ".csv" file with 25,000 observations, which has monthly temperature data from 2016-2018 with the associated latitude and longitude values. I have tried using geom_raster to map this data but I get the following error message
Error: cannot allocate vector of size 39.7 Gb
In addition: Warning messages:
1: In f(...) :
Raster pixels are placed at uneven horizontal intervals and will be shifted. Consider using geom_tile() instead.
2: In f(...) :
Raster pixels are placed at uneven vertical intervals and will be shifted. Consider using geom_tile() instead
So of course, I have also tried using geom_tile but when I run the code I get a blank map with no color even though I have specified both fill and color. Here is some sample data similar to my data frame, please note that my real data for latitude and longitude values are not evenly spaced by seq(...,...,0.1) (I'm not sure how to make sample data without the sequencing, sorry) so you won't get the same error as me, and the code will work
#In my data frame the lat and long values are not equally spaced!
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$Temp = runif(nrow(mapoc_temp))
Here is my code for geom_raster which gives me the error I mentioned
library(mapdata)
library(ggplot2)
#map I'm using for ggplot
Canada = map_data("wildfires", "Canada")
ggplot(mapoc_temp, aes(x=Longitude, y=Latitude)) +
#try to map my temp on the ocean
geom_raster(aes(fill = Temp, 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)) +
#get months
facet_wrap(vars(month))
here is the code when I try geom_tile, again I noticed with my sample data it works, but with my real data it doesn't and I believe it has something to do with my coordinates not being equal distances apart.
ggplot(mapoc_temp, aes(x=Longitude, y=Latitude)) +
geom_tile(aes(fill = Temp, x = Longitude, y = Latitude), colour = mapoc_temp$Temp) +
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)) +
facet_wrap(vars(month))
here is the picture I get with geom_tile
and here is roughly what I am trying to produce, but obviously, 12 of these maps because I want a map for each month, with better resolution (if possible, but at this point, I'll take any map colored with my temperature data).
I have a feeling I'll have to do something more along the lines with this type of code (a snippet of something I found a while ago), but I have tried manipulating this with no success. Any suggestions?
#my CRS value!
latlong = "+proj=longlat +datum=NAD83 +no_defs +ellps=GRS80 +towgs84=0,0,0"
#for transforming
planar ="+proj=utm +zone=20 +datum=NAD83 +units=km +no_defs +ellps=GRS80 +towgs84=0,0,0"
out <- x%>%
st_as_sf(coords=c("Longitude","Latitude"),crs=latlong)%>%
st_transform(planar)%>%
st_coordinates()%>%
raster::rasterize(.,grid,field=xyz[,3],fun=rasterFun)%>%
raster::projectRaster(.,crs=latlong)%>%
raster::rasterToPolygons(.)%>% # this part is slow
st_as_sf()%>%
rename(MAP = layer)
You have sort of answered your own question with the example data you offered. The geom_raster and geom_tile functions have limits to their use. A big one is that because they require the data to be on an even grid, with very high res station data the machine will try to create an even grid before plotting, hence the error of needing 39.7 GB of memory. By rounding your lon/lat values to an even 0.1x0.1 grid the machine is now able to plot the data in the other answers in this post. Try running the following code chunk on your data.
mapoc_temp <- mapoc_temp %>%
ungroup() %>%
mutate(Longitude = plyr::round_any(Longitude, 0.1),
Latitude = plyr::round_any(Latitude, 0.1))
You may change the level of rounding as you prefer, but avoid going too fine scale unless it is absolutely necessary. Once your data have been rounded to an even grid you can plot them with the following chunk.
ggplot(mapoc_temp, aes(x = Longitude, y = Latitude)) +
borders(fill = "grey80") +
geom_raster(aes(fill = Temp)) +
coord_quickmap(xlim = c(-64.5,-62.8), ylim = c(42.7,45)) +
facet_wrap(~month)
There is no need to create any sf shape polygons or add any CRS information to the plot. The tidyverse is not designed to utilise this information and in my opinion it only complicates things unnecessarily to bring in the sf package. I hope this helps!
It looks like the geom_polygon(mapping layer) was overplotting the geom_tile layer. Below is an example using your example data with geom_tile called last, and with alpha set to 0.4 to show the map beneath.
#In my dataframe the lat and long values are not equally spaced!
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$Temp = runif(nrow(mapoc_temp))
library(mapdata)
#> Loading required package: maps
library(ggplot2)
#map I'm using for ggplot
canada = map_data("worldHires", "Canada")
## Use geom_raster as the last layer in the ggplot2 call,
## otherwise the polygons plot over the tiles.
## Below alpha is set on the raster layer to show underlying map.
ggplot(mapoc_temp, aes(x=Longitude, y=Latitude)) +
#try to map my temp on ocean
geom_polygon(data = canada, aes(x=long, y=lat, group=group), colour="grey50", fill = 'grey55')+
geom_raster(aes(fill = Temp, x = Longitude),alpha = .4, interpolate = TRUE) +
coord_sf(xlim=c(-64.5,-62.8), ylim=c(42.7,45)) +
#get months
facet_wrap(vars(month))
Created on 2020-02-22 by the reprex package (v0.3.0)
You can also set fill= NA within your geom_polygon function if you have that layer on top of the geom_raster
A few lines of code to expose my problem. When I work with a map of
the world and I introduce a projection, I always end up with some
weird looking horizontal lines.
Please have a look at
https://www.rdocumentation.org/packages/ggplot2/versions/1.0.0/topics/coord_map
from where I take the example for New Zeland
library(ggplot2)
nz <- map_data("nz")
# Prepare a map of NZ
nzmap <- ggplot(nz, aes(x = long, y = lat, group = group)) +
geom_polygon(fill = "white", colour = "black")
# Plot it in cartesian coordinates
nzmap
# With correct mercator projection
nzmap + coord_map()
which works beautifully. Now let us do the same with the world
world <- map_data("world")
# Prepare a map of the world
worldmap <- ggplot(world, aes(x = long, y = lat, group = group)) +
geom_polygon(fill = "white", colour = "black")
# Plot it in cartesian coordinates
worldmap
##but the following is a disaster!
# With correct mercator projection
worldmap + coord_map()
I see this issue of the horizontal lines with a projection has been
going on for quite a while, but I was able to find only seasoned posts
and I had assumed this was fixed long ago.
Please find below my sessionInfo.
Is there any solution to this? Is it still an open bug?
This is a pretty common problem in ggplot, but happily it is easily fixed:
worldmap + coord_map(xlim=c(-180,180))
produces
solution from: Why does coord_map produce a weird output?
I've been having difficulties with a map I created in R. I'm trying to make a map with a grid where in each square, there's a value corresponding to a dataframe. So far, I made the shapefile and the script following some tutorials and posts from here (Download), but the final result got kinda weird.
library(xlsx)
library(ggplot2)
library(sp)
library(raster)
library(plyr)
library(dplyr)
library(tidyr)
library(sp)
library(raster)
library(rgeos)
library(rgbif)
library(viridis)
library(gridExtra)
library(rasterVis)
library(ggplot2)
library(maps)
library(rgdal)
br <- readOGR(choose.files(), "brgrid")
plot(br)
class(br)
str(br#data)
br#data$id <- rownames(br#data)
br.df <- fortify(br)
br.df <- join(br.df, br#data, by="id")
str(br.df)
tail(br.df)
names(br.df)
tail(br.df$id)
dados <- read.xlsx("ptsgrid.xlsx",6)
names(dados)
br.df <- merge(br.df, dados, by.x="id", by.y="id", all.x=T, a..ly=F)
str(br.df)
ggp <- ggplot(data=br.df, aes(x=long, y=lat, group=group))
ggp <- ggp + geom_polygon(aes(fill=value)) # draw polygons
ggp <- ggp + geom_path(color="grey", linestyle=1) # draw boundaries
ggp <- ggp + coord_equal()
ggp <- ggp + scale_fill_gradient(low = "#ffffcc", high = "#ff4444",
space = "Lab", na.value = "grey50",
guide = "colourbar")
print(ggp)
I want to know why the lines got crossed in the map, and how to fix it. Also, I wanna know if it's possible to omit some squares (I only have interest in coastal region, so it'll look better if I omit the rest). And finally, I don't know why the map boundaries got "overlayed" (maybe a projection issue?).
Welcome to Stack Overflow! What have you done so far/what does your code look like? I will share with you a map/code I made that functions as I intended, so you can replace values in my code with what you need for your needs/with your data Below is code for a map I created in R for income in the United States:
library(maps)
library(ggplot2)
usa=map_data("state")
ggplot(usa)+geom_polygon(aes(x=long,y=lat,group=group,fill=region),color="white")+coord_fixed(1.3)+guides(fill=FALSE,color=FALSE)
The result of the above code:
I downloaded your data set. I did not examine your code. But I think when you created br.df using merge(), order got messed up. In your code, I am talking about this line (br.df<-merge(br.df, dados, by.x="id", by.y="id", all.x=T, a..ly=F). You may want to check this question. You wanted to combine all data sets. But you do not have to do that.
In your data set, dados, you have 148 data points. But you have 150 grids in your map data. So I modified your EXCEL data; I added id = 0 and id = 149. Each data point has 0 and 495, respectively. As long as there is a common column name (in this case, id), you can do the following. I used geom_cartogram() in the ggalt package. The second geom_cartogram() is adding colors to the grids.
library(rgdal)
library(ggplot2)
library(ggalt)
library(readxl)
# Create a map data
foo <- readOGR(dsn = "brgrid.shp")
mygrid <- fortify(foo)
# Import the EXCEL data
dados <- read_excel("ptsgrid.xlsx", sheet = 6)
ggplot() +
geom_cartogram(data = mygrid, map = mygrid,
aes(x = long, y = lat, map_id = id),
color = "black", alpha = 0.5) +
geom_cartogram(data = dados, map = mygrid,
aes(fill = value, map_id = id)) +
scale_fill_gradient(low = "#ffffcc", high = "#ff4444",
space = "Lab", na.value = "grey50",
guide = "colourbar")
As you can see below, there is a weird displaying problem on the maps I made using ggplots. The same problem seems to happen with any projection.
Here is the code:
Only the packages maps and ggplot2 are needed
mapWorld <- borders("world", colour="gray50", fill="black")
ggplot() + mapWorld +
coord_map("mercator") +
ylim(-90,90)
Apparently the problem is caused by the polygons that cross the 0 coordinate, the place in which the world merges. R dont knows how to close those polygons and projects them all around the world.
This method recreates the polygons and prevents them from crossing the 0 coordinate (xlim and ylim). It works with any kind of projection.
require(ggplot2)
require(PBSmapping)
require(data.table)
mapWorld <- map_data("world")
setnames(mapWorld, c("X","Y","PID","POS","region","subregion"))
worldmap = clipPolys(mapWorld, xlim=xlim,ylim=ylim, keepExtra=TRUE)
ggplot() + geom_polygon(data = mapWorld, aes(X,Y,group=PID))
why you need to use?
ggplot() + mapWorld +
coord_map("mercator") +
ylim(-90,90)
if u use just
ggplot() + mapWorld
It works perfectly