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.
I am practicing the ggplot2 grammar of graphics on World maps using the base R dataset and the ggplot2 and mapproj packages.
When building a map that colours countries by a random variable (called "CountryColour" in the following example):
world_map <- map_data("world")
country_colours <- data.frame(region = c(names(table(world_map$region))),
colour= sample(c(1:20), length(names(table(world_map$region))), replace = TRUE))
world_map <- merge(world_map, country_colours)
world_map <- world_map[order(world_map$region, world_map$order),]
I happened to include the aes(fill) argument in the ggplot component:
ggplot(world_map[abs(world_map$long) < 180,], aes(x=long, y=lat, group=group, fill=colour)) +
geom_polygon(color="black") +
coord_map(projection = "mercator")
Now, if I include it in the ggplot() component itself I get EXACTLY the same output:
ggplot(world_map[abs(world_map$long) < 180,], aes(x=long, y=lat, group=group)) +
geom_polygon(aes(fill=colour), color="black") +
coord_map(projection = "mercator")
I would like to understand the conceptual difference between placing the fill function in one place or the other.
I have a shapefile showing the map of England with regions mapped on it:
England <- readOGR(dsn = "...")
England.fort <- fortify(England, region='regionID')
England.fort <-England.fort[order(England.fort$order), ]
giving me England.fort:
England.fort
>long
>lat
>order
>hole
>piece
>id #contains the region IDs
>group #contains the region IDs
>Total #I want to plot this
Shapefile from here: https://geoportal.statistics.gov.uk/Docs/Boundaries/Local_authority_district_(GB)_2014_Boundaries_(Generalised_Clipped).zip
I want to plot the regions showing the total number of people in each:
p <- ggplot(data=England.fort, aes(x=long, y=lat, group=group, fill="Total")) +
geom_polygon(colour='black', fill='white') + theme_bw()
But It gives me a blank map off England with all the regions white.
ggplot(data=England.fort, aes(x=long, y=lat, group=group, Fill=Total)) +
geom_polygon() +
theme_bw()
Does the trick. Thanks
I am trying to plot some geolocational data pertaining to Great Britain and Ireland in ggplot. Running the following code, I can successfully map some values from this tab-separated file onto the GBR shapefile data found here (country = Great Britain):
library(rgdal)
library(ggplot2)
library(rgeos)
library(plyr)
#this data comes from http://www.gadm.org/country (download the Great Britain data set, and set path to the downloaded data's topmost directory)
shape.dir <- "C:\\Users\\Douglas\\Desktop\\estc_clean_analysis\\geoanalysis\\GBR_adm"
#the first parameter we pass to readOGR species the location of the shapefile we want to read in; layer indicates which shapefile in that dir we want to read in. Data via UK shapefile from http://www.gadm.org/country
uk.shp <- readOGR(shape.dir, layer = "GBR_adm2")
#read in csv with values by county
small_geo_data <- read.csv(file = "small_geo_sample.txt", header=TRUE, sep="\t", na.string=0, strip.white=TRUE)
#fortify prepares the data for ggplot
uk.df <- fortify(uk.shp, region = "ID_2") # convert to data frame for ggplot
#now combine the values by id values in both dataframes
combined.df <- join(small_geo_data, uk.df, by="id")
#now build plot up layer by layer
ggp <- ggplot(data=combined.df, aes(x=long, y=lat, group=group))
ggp <- ggp + geom_polygon(aes(fill=value)) # draw polygons
ggp <- ggp + geom_path(color="grey", linestyle=2) # draw boundaries
ggp <- ggp + coord_equal()
ggp <- ggp + scale_fill_gradient(low = "#ffffcc", high = "#ff4444",
space = "Lab", na.value = "grey50",
guide = "colourbar")
ggp <- ggp + labs(title="Plotting Values in Great Britain")
# render the map
print(ggp)
Running that code yields:
What I would like to do now is to add data pertaining to Ireland to my plot. I downloaded the "IRL" shapefiles from the same site that provided the GBR shapefiles, but then I ran into a series of roadblocks. I have tried combining IRL_adm1.csv and GBR_adm2.csv (renaming the id values in the former to avoid conflicts), but nothing has worked yet. Before hacking the rest of the way to a kludgy solution, I thought I should stop and post the following question on SO: Is there a reasonably straightforward way to combine the GBR and IRL files in a single plot? I would be very grateful for any ideas or suggestions others can offer on this question.
If your Britain and Ireland shapefiles use the same projection/CRS, you can add both layers to a plot without needing to join them like this:
ggplot() +
geom_polygon(data = gbrshapefortified, aes(long, lat, group = group)) +
geom_polygon(data = irlshapefortified, aes(long, lat, group = group)) +
coord_equal()
I.e. you don't need to combine them if you're just plotting layers and the thematic values you're plotting don't depend on each other.
I'm trying to draw a choropleth map of Germany showing poverty rate by state (inspired by this question).
The problem is that some of the states (Berlin, for example) are completely surrounded by other states (Brandenburg), and I'm having trouble getting ggplot to recognize the "hole" in Brandenburg.
The data for this example is here.
library(rgdal)
library(ggplot2)
library(RColorBrewer)
map <- readOGR(dsn=".", layer="germany3")
pov <- read.csv("gerpoverty.csv")
mrg.df <- data.frame(id=rownames(map#data),ID_1=map#data$ID_1)
mrg.df <- merge(mrg.df,pov, by="ID_1")
map.df <- fortify(map)
map.df <- merge(map.df,mrg.df[,c("id","poverty")], by="id")
ggplot(map.df, aes(x=long, y=lat, group=group)) +
geom_polygon(aes(fill=poverty))+
geom_path(colour="grey50")+
scale_fill_gradientn(colours=brewer.pal(5,"OrRd"))+
labs(x="",y="")+ theme_bw()+
coord_fixed()
Notice how the colors for Berlin and Brandenburg (in the northeast) are identical. They shouldn't be - Berlin's poverty rate is much lower than Brandenburg. It appears that ggplot is rendering the Berlin polygon and then rendering the Brandenburg polygon over it, without the hole.
If I change the call to geom_polygon(...) as suggested here, I can fix the Berlin/Brandenburg problem, but now the three northernmost states are rendered incorrectly.
ggplot(map.df, aes(x=long, y=lat, group=group)) +
geom_polygon(aes(group=poverty, fill=poverty))+
geom_path(colour="grey50")+
scale_fill_gradientn(colours=brewer.pal(5,"OrRd"))+
labs(x="",y="")+ theme_bw()+
coord_fixed()
What am I doing wrong??
This is just an expansion on #Ista's answer, which does not require that one knows which states (Berlin, Bremen) need to be rendered last.
This approach takes advantage of the fact that fortify(...) generates a column, hole which identifies whether a group of coordinates are a hole. So this renders all regions (id's) with any holes before (e.g. underneath) the regions without holes.
Many thanks to #Ista, without whose answer I could not have come up with this (believe me, I spent many hours trying...)
ggplot(map.df, aes(x=long, y=lat, group=group)) +
geom_polygon(data=map.df[map.df$id %in% map.df[map.df$hole,]$id,],aes(fill=poverty))+
geom_polygon(data=map.df[!map.df$id %in% map.df[map.df$hole,]$id,],aes(fill=poverty))+
geom_path(colour="grey50")+
scale_fill_gradientn(colours=brewer.pal(5,"OrRd"))+
labs(x="",y="")+ theme_bw()+
coord_fixed()
You can plot the island polygons in a separate layer, following the example on the ggplot2 wiki. I've modified your merging steps to make this easier:
mrg.df <- data.frame(id=rownames(map#data),ID_1=map#data$ID_1)
mrg.df <- merge(mrg.df,pov, by="ID_1")
map.df <- fortify(map)
map.df <- merge(map.df,mrg.df, by="id")
ggplot(map.df, aes(x=long, y=lat, group=group)) +
geom_polygon(aes(fill=poverty), color = "grey50", data =subset(map.df, !Id1 %in% c("Berlin", "Bremen")))+
geom_polygon(aes(fill=poverty), color = "grey50", data =subset(map.df, Id1 %in% c("Berlin", "Bremen")))+
scale_fill_gradientn(colours=brewer.pal(5,"OrRd"))+
labs(x="",y="")+ theme_bw()+
coord_fixed()
As an unsolicited act of evangelism, I encourage you to consider something like
library(ggmap)
qmap("germany", zoom = 6) +
geom_polygon(aes(x=long, y=lat, group=group, fill=poverty),
color = "grey50", alpha = .7,
data =subset(map.df, !Id1 %in% c("Berlin", "Bremen")))+
geom_polygon(aes(x=long, y=lat, group=group, fill=poverty),
color = "grey50", alpha= .7,
data =subset(map.df, Id1 %in% c("Berlin", "Bremen")))+
scale_fill_gradientn(colours=brewer.pal(5,"OrRd"))
to provide context and familiar reference points.
Just to add another small improvement to #Ista's and #jhoward's answers (thanks a lot for your help!).
The modification of #jhoward could be easily wrapped in a small function like this
gghole <- function(fort){
poly <- fort[fort$id %in% fort[fort$hole,]$id,]
hole <- fort[!fort$id %in% fort[fort$hole,]$id,]
out <- list(poly,hole)
names(out) <- c('poly','hole')
return(out)
}
# input has to be a fortified data.frame
Then, one doesn't need to recall every time how to extract holes info. The code would look like
ggplot(map.df, aes(x=long, y=lat, group=group)) +
geom_polygon(data=gghole(map.df)[[1]],aes(fill=poverty),colour="grey50")+
geom_polygon(data=gghole(map.df)[[2]],aes(fill=poverty),colour="grey50")+
# (optionally). Call by name
# geom_polygon(data=gghole(map.df)$poly,aes(fill=poverty),colour="grey50")+
# geom_polygon(data=gghole(map.df)$hole,aes(fill=poverty),colour="grey50")+
scale_fill_gradientn(colours=brewer.pal(5,"OrRd"))+
labs(x="",y="")+ theme_bw()+
coord_fixed()
Alternatively you could create that map using rworldmap.
library(rworldmap)
library(RColorBrewer)
library(rgdal)
map <- readOGR(dsn=".", layer="germany3")
pov <- read.csv("gerpoverty.csv")
#join data to the map
sPDF <- joinData2Map(pov,nameMap='map',nameJoinIDMap='VARNAME_1',nameJoinColumnData='Id1')
#default map
#mapPolys(sPDF,nameColumnToPlot='poverty')
colours=brewer.pal(5,"OrRd")
mapParams <- mapPolys( sPDF
,nameColumnToPlot='poverty'
,catMethod="pretty"
,numCats=5
,colourPalette=colours
,addLegend=FALSE )
do.call( addMapLegend, c( mapParams
, legendLabels="all"
, legendWidth=0.5
))
#to test state names
#text(pov$x,pov$y,labels=pov$Id1)