How to specify countries/region while creating maps in R? - r

map("usa") by default displays a map without Alaska and Hawaii. map("world") has Antartica by default. Is there any way to say "include alaska", "exclude antartica" etc?

Quick answer:
nams <- map("world", namesonly=TRUE, plot=FALSE)
map("world", region=nams[-grep("Antarctica", nams)])
Longer answer:
The maps data in "world" is referenced by region names and these are generally character data in "continent:country" or "continent:subregion" format. To get those names which are in an external database, you need to first use maps("world" , ...) with parameters that return only the names and not all of hte other coordinates. If you want to find all the "Antarctica" containing entries you need to use grep() to identify their position in the returned names vector.

If you looking just for those areas, the brutal solution would be to use world map, specify USA as a region and define latitude/longitude to create limits, so the map will only display specific area:
library(maps)
long <- c(-180,-50)
lat <- c(10,80)
map("world",regions=".*usa",xlim=long,ylim=lat)

Related

Extract from OSM Planet File is incomplete

I'm fairly new to the OSM world and I need to extract all water related polygons from the OSM planet file, except for ocean polygons. I know there is some product from a university in Tokyo, but it's from 2016 and I need it as up to date as possible.
I already extracted a good bit of it with the following code. However, comparing the resulting layers with the OSM basemap in QGIS I noticed that some parts are missing. Even though they have the same flags and relations like other parts that were extracted. I know that some parts of rivers are digitalized as lines and not polygons, so it's okay that those are missing. The missing parts are definitely polygons, since I could extract one of them with the same flags through the QuickOSM plug-in in QGIS. Also the OSM Basemap shows clearly that those areas must be polygons (see screenshot).
Is there a mistake in my code or did I make an mistake with the flags? My code however throws no errors and everything seems to be working except for the missing parts.
Thanks in advance!
Here is the code so far:
library(gdalUtils)
library(rgdal)
library(sf)
# extracting all layers with flag "natural = water"
path_pbf <- "path/to/planet_file.osm.pbf"
ogr2ogr(src_datasource_name = path_pbf,
"OSM_Waterbodies.gpkg",
f = "GPKG",
sql = "SELECT * FROM multipolygons WHERE natural = 'water'",
progress = T)
# extracting all layers with flag "other_tags LIKE waterway"
ogr2ogr(src_datasource_name = path_pbf,
"OSM_Waterways.gpkg",
f = "GPKG",
sql = "SELECT * FROM multipolygons WHERE other_tags LIKE '%waterway%'",
progress = T)
waterways <- st_read("OSM_Waterways.gpkg")
waterways$rm <- NA
# select only certain polygons since waterways also includes dams etc
check <- "*riverbank*|*river*|*stream*|*tidal channel*|*canal*|*drain*|*ditch*|*lake*"
# mark polygons which are not part of the desired selection with "remove" flag
for(i in 1:nrow(waterways)){
if (!grepl(check, waterways$other_tags[i])){
waterways$rm[i] <- "Remove"
}
}
# drop rows with "remove" flag
index <- which(waterways$rm == "Remove")
waterways <- waterways[-index,]
st_write(waterways, "OSM_Waterways_clean.gpkg", driver = "GPKG")
P.S.: The code is probably not the most efficient one, but it's not about efficiency, since I will probably run it once or twice.
It looks like you're only extracting multiploygons, which are used in OSM when a shape isn't a simple polygon. This means that river sections with islands in them will be extracted, but many simple river sections will not, as they are just mapped as closed ways (An example from your screenshot). I don't have the OSM Global file on hand to check, but I would imagine that it's as simple as running the ogr2ogr functions again with ways instead of multipolygons in the SQL, and then checking that the ways are closed (likely, check that the first and last nodes are identical, as a quick search suggests that ogr2ogr doesn't provide a way to check for closed ways explicitly).

making a choropleth from SpatialPolygonsDataFrame- ggplot vs ggplot2 vs plot?

I have a shapefile, specifically, a SpatialPolygonsDataFrame, called cdtract. that contains one variable for each district called varcount. varcount is either "NA" or 1. When I do
plot(cdtract)
...I see the map printed out but I don't see the tracts that are '1' in varcount marked any differently from those that are 'NA.' I ideally want to have a spectrum of values in varcount and see those reflected in different colors. I considered using ggplot but according to this post here that is very resource intensive and it might be better to use plot() instead of ggplot() to create the choropleth. But I'm really not sure how to go about it. I am using a different shapefile from states/countries so am not sure that the choroplethr package is the way to go.
Can someone explain how to take a SpatialPolygonsDataFrame and turn it into a choropleth, efficiently? Thanks!
Shamefully taken from Ari's post on gis.stackexchange.com. See the link for pictures. There are more examples here.
library(sp)
Srs1 = Polygons(list(Polygon(cbind(c(2,4,4,1,2),c(2,3,5,4,2)))), "s1")
Srs2 = Polygons(list(Polygon(cbind(c(5,4,2,5),c(2,3,2,2)))), "s2")
SpDF <- SpatialPolygonsDataFrame( SpatialPolygons(list(Srs1,Srs2)),
data.frame(z=1:2, row.names=c("s1","s2") ) )
spplot(SpDF, zcol="z")

How can I see all argument options in R?

This seems like a stupid question, but I have not been able to find the answer by googling.
R Documentation often does not outline all possible values for particular arguments. Is there a command to print that information?
For example, I would like to draw some maps using the function map() in the maps package. The R Documentation states for the region argument:
regions: character vector that names the polygons to draw. Each
database is composed of a collection of polygons, and each polygon has
a unique name. When a region is composed of more than one polygon, the
individual polygons have the name of the region, followed by a colon
and a qualifier, as in michigan:north and michigan:south. Each element
of regions is matched against the polygon names in the database and,
according to exact, a subset is selected for drawing. The default
selects all polygons in the database.
Is it possible to get a list of the region names?
You can see the arguments and defaults with:
args(map)
I believe you are looking for elements in the database and not arguments since the map function will not know what database you are passing it. Its default is 'world'.
w <- map('world')
str(w) # not necessary, but good to look at
w$names
And further:
canada <- map(region = 'Canada')
canada$names

shade between two latitudes on country map

I want to plot a simple outline of a country map and have an area between two latitudes shaded grey.
I think I need to use the rworldmap library but I'm not exactly sure how to achieve what I want.
Good suggestions by others. I initially thought that you might want the latitudinal shading to extend beyond the country borders. If that's the case here's a quick and dirty solution using rworldmap for the map, sp to plot it and polygon from base graphics to add the latitude shading. You could then modify using spTransform from rgdal if you want to project, or the suggestion from Sam if you want to crop to country borders.
library(rworldmap)
library(sp)
sPDFworld <- getMap(resolution="low")
#getMap() maps have ADMIN & NAME fields with country names formatted differently
#use sPDFworld$ADMIN sPDFworld$NAME to check
country <- "United Kingdom"
#to plot just this country (uses sp)
plot(sPDFworld[ sPDFworld$ADMIN==country, ] )
#shade a latitude region
polygon(x=c(-180,-180,180,180),y=c(55,60,60,55),col=adjustcolor('grey',alpha.f=0.5),border=NA)
I'd do something as in https://stackoverflow.com/a/13986029/1358308 . You can crop down to your "rectangle" as needed and then just plot the interiour of the resulting polygon as "grey", and don't print the borders by setting them to NA.
If you plot this "after" the larger outline (using the same polygon, before doing the intersection) then you should just get the country filled in. If you want the "water" filled in using a different color, you can do this "first". The later plot(x, add=TRUE) will plot the new things "on top" so you won't see the working behind.
Hope that makes sense!

Developing Geographic Thematic Maps with R

There are clearly a number of packages in R for all sorts of spatial analysis. That can by seen in the CRAN Task View: Analysis of Spatial Data. These packages are numerous and diverse, but all I want to do is some simple thematic maps. I have data with county and state FIPS codes and I have ESRI shape files of county and state boundaries and the accompanying FIPS codes which allows joining with the data. The shape files could be easily converted to other formats, if needed.
So what's the most straight forward way to create thematic maps with R?
This map looks like it was created with an ESRI Arc product, but this is the type of thing I would like to do with R:
alt text http://www.infousagov.com/images/choro.jpg Map copied from here.
The following code has served me well. Customize it a little and you are done.
(source: eduardoleoni.com)
library(maptools)
substitute your shapefiles here
state.map <- readShapeSpatial("BRASIL.shp")
counties.map <- readShapeSpatial("55mu2500gsd.shp")
## this is the variable we will be plotting
counties.map#data$noise <- rnorm(nrow(counties.map#data))
heatmap function
plot.heat <- function(counties.map,state.map,z,title=NULL,breaks=NULL,reverse=FALSE,cex.legend=1,bw=.2,col.vec=NULL,plot.legend=TRUE) {
##Break down the value variable
if (is.null(breaks)) {
breaks=
seq(
floor(min(counties.map#data[,z],na.rm=TRUE)*10)/10
,
ceiling(max(counties.map#data[,z],na.rm=TRUE)*10)/10
,.1)
}
counties.map#data$zCat <- cut(counties.map#data[,z],breaks,include.lowest=TRUE)
cutpoints <- levels(counties.map#data$zCat)
if (is.null(col.vec)) col.vec <- heat.colors(length(levels(counties.map#data$zCat)))
if (reverse) {
cutpointsColors <- rev(col.vec)
} else {
cutpointsColors <- col.vec
}
levels(counties.map#data$zCat) <- cutpointsColors
plot(counties.map,border=gray(.8), lwd=bw,axes = FALSE, las = 1,col=as.character(counties.map#data$zCat))
if (!is.null(state.map)) {
plot(state.map,add=TRUE,lwd=1)
}
##with(counties.map.c,text(x,y,name,cex=0.75))
if (plot.legend) legend("bottomleft", cutpoints, fill = cutpointsColors,bty="n",title=title,cex=cex.legend)
##title("Cartogram")
}
plot it
plot.heat(counties.map,state.map,z="noise",breaks=c(-Inf,-2,-1,0,1,2,Inf))
Thought I would add some new information here since there has been some activity around this topic since the posting. Here are two great links to "Choropleth Map R Challenge" on the Revolutions blog:
Choropleth Map R Challenge
Choropleth Challenge Results
Hopefully these are useful for people viewing this question.
All the best,
Jay
Check out the packages
library(sp)
library(rgdal)
which are nice for geodata, and
library(RColorBrewer)
is useful for colouring. This map is made with the above packages and this code:
VegMap <- readOGR(".", "VegMapFile")
Veg9<-brewer.pal(9,'Set2')
spplot(VegMap, "Veg", col.regions=Veg9,
+at=c(0.5,1.5,2.5,3.5,4.5,5.5,6.5,7.5,8.5,9.5),
+main='Vegetation map')
"VegMapFile" is a shapefile and "Veg" is the variable displayed. Can probably be done better with a little work. I don`t seem to be allowed to upload image, here is an link to the image:
Take a look at the PBSmapping package (see borh the vignette/manual and the demo) and
this O'Reilly Data Mashups in R article (unfortunately it is not free of charge but it worth 4.99$ to download, according Revolutions blog ).
It is just three lines!
library(maps);
colors = floor(runif(63)*657);
map("state", col = colors, fill = T, resolution = 0)
Done!!
Just change the second line to any vector of 63 elements (each element between 0 and 657, which are members of colors())
Now if you want to get fancy you can write:
library(maps);
library(mapproj);
colors = floor(runif(63)*657);
map("state", col = colors, fill = T, projection = "polyconic", resolution = 0);
The 63 elements represent the 63 regions whose names you can get by running:
map("state")$names;
The R Graphics Gallery has a very similar map which should make for a good starting point. The code is here: www.ai.rug.nl/~hedderik/R/US2004 . You'd need to add a legend with the legend() function.
If you stumble upon this question in the 2020ies, use the magnificent tmap package. It's very simple and straightforward and revolutionized making maps in R. Do not bother to investigate this complicated code.
Check the vignette here.

Resources