Trouble merging shapefiles in R - r

I am having trouble merging shapefiles in R. Here is my code thus far:
library(rgdal)
library(maptools)
library(gridExtra)
setwd("/Users/Cornelius/Dropbox/Cornelius_Sharedfolder")
#Load a geodatabase
fgdb = "/Users/Cornelius/Dropbox/Cornelius_Sharedfolder/RwandaGDB.gdb"
subset(ogrDrivers(), grepl("GDB", name))
fc_list = ogrListLayers(fgdb)
print(fc_list)
#Get the shapefiles from the geodatabase:
Residence=readOGR(dsn=fgdb, layer="RĂ©sidence")
Territoire = readOGR(dsn=fgdb,layer="Territoire")
Chefferie=readOGR(ds=fgdb, layer="Chefferie")
Sous_Chefferie=readOGR(ds=fgdb, layer="Sous_Chefferie")
RwandaPre2002=readOGR(ds=fgdb, layer="RwandaPre2002")
Country_Boundary2012=readOGR(ds=fgdb, layer="Country_Boundary2012")
Province_Boundary2012=readOGR(ds=fgdb, layer="Province_Boundary2012")
Sector_Boundary2012=readOGR(ds=fgdb, layer="Sector_Boundary2012")
District_Boundary2012=readOGR(ds=fgdb, layer="District_Boundary2012")
Cell_Boundary2012=readOGR(ds=fgdb, layer="Cell_Boundary2012")
x = list(Residence, Territoire, Sous_Chefferie, RwandaPre2002, Country_Boundary2012, Province_Boundary2012, Sector_Boundary2012, District_Boundary2012, Cell_Boundary2012)}
This all goes fine. However, when I try to merge two shapefiles - for example, Residence and Territoire, and use the following code, it gives me an error:
test_bind <-spRbind(Territoire, Residence)
The error says: "non-unique polygon IDs."
I'm not sure what this means. Could you please help?

Related

Global cartogram in R

I am trying to create a global cartogram using the cartogram package in R. I am trying to use the data from wrld_simpl. What I expect is a cartogram in which the Population ("Pop2005" variable) is plotted. The code I have developed is this:
data(wrld_simpl)
world<-wrld_simpl
world_sf = st_as_sf(world)
world_sf_proj = st_transform(world_sf, crs = 3785)
world_cartogram <- cartogram_cont(world_sf_proj, "POP2005")
plot(world_cartogram)
Nonetheless, this has resulted in the following figure:
Do you know what is wrong with the code? Maybe the CRS? I have tried to use others CRS but I got the following error:
"Error: Using an unprojected map. This function does not give correct centroids and distances for longitude/latitude data:
Use "st_transform()" to transform coordinates to another projection."
Taken from this documentation, it is stated that
The default plot of an sf object is a multi-plot of all attributes, up
to a reasonable maximum
If you want to use the base R plot function, then use st_geometry(your_map) to plot (the geometry) an sf object.
Another possibility (which I don't recommend) is to set plot options to 1 plot maximum (options(sf_max.plot=1)), but this plots the first variable, and it might not be the best idea.
library(sf)
library(spData)
library(cartogram)
library(tidyverse)
world_sf = st_as_sf(world)
world_sf_proj = st_transform(world_sf, crs = 3785)
world_cartogram <- cartogram_cont(world_sf_proj, "pop")
plot(st_geometry(world_cartogram))
Now, sf is particularly well suited with ggplot2 and the tidyverse. In that setting, just use ggplot in combination with geom_sf.
ggplot(world_cartogram) +
geom_sf()

tm_text produces duplicate text in tmap

I'm trying to do a map using library tmap and this dataset.
Following this discussion, I'm using the following simple code:
library(tmap)
library(geobr)
library(sf)
rg = st_as_sf(polygons_regioes_adm_sp)
tm_shape(rg) +
tm_polygons("regiao_administrativa",
legend.show = F) +
tm_text("regiao_administrativa", size = 1/2)
That yields the following map with overlapping DUPLICATE text. I tried insert remove.overlap = TRUE inside tm_text but this doesn't worked better.
Furthermore i'm getting the following message:
old-style crs object detected; please recreate object with a recent sf::st_crs()
In this context, How I get a map without duplicate text ?
Your code to display the map with the tmap library is fine. The problem is that the sf object polygons_regioes_adm_sp has a mixture of POLYGON and MULTIPOLYGON. So, you just need to simplify the sf object by running the st_cast() function.
As for the projection problem, you just need to specify the EPSG code to assign a recent form of the CRS to the sf object (NB: as for the warning message - cf.below - do not worry, it is fine)
So, please find below the code to display correctly the names of the administrative regions.
library(tmap)
library(sf)
library(dplyr) # please, do not forget to load this library
rg <- polygons_regioes_adm_sp %>%
st_set_crs(4674) %>%
st_cast()
#> old-style crs object detected; please recreate object with a recent sf::st_crs()
#> Warning: st_crs<- : replacing crs does not reproject data; use st_transform for
#> that
tm_shape(rg) +
tm_polygons("regiao_administrativa",
legend.show = F) +
tm_text("regiao_administrativa", size = 1/2)
Created on 2021-11-13 by the reprex package (v2.0.1)

"Wasn't able to determine range of domain" for ColorNumeric

I'm trying to create a choropleth map in R. I've merged my shapefiles and data files. I'm trying to create a palette for the different colours I want my data to display in on my choropleth. When I use the colorNumeric function it returns an error message.
library(leaflet)
library(rgdal)
library(tigris)
library(dplyr)
LAsMap <- readOGR(dsn = "C:/Users/LocalAuthorityShapefiles",
layer = "Local_Authority_Districts_December_2017_Generalised_Clipped_Boundaries_in_United_Kingdom_WGS84")
data <- read.csv(file = "C:/projects/N123.csv")
data_merged_map <- geo_join(LAsMap, data, "lad17cd", "lad17nm")
mypalette <- colorNumeric( palette="viridis", domain=data_merged_map$N456)
I expect the output to just run the code and create a palette in my workspace but instead the "Wasn't able to determine range of domain" error message appears.
For me, this happened because I had -Inf values. Originally they were 0s, but I log10() transformed the vector, and that's what caused them to be -Inf for me.

ggplot2 map is blank

I am using similar to code to other scripts with different shape files from Statistics Canada. However, I can't get a simple script to work with a provincial map. I think the problem is simple but I can't see it.
setwd("D:\\OneDrive\\lfs_stuff")
project_folder<-getwd()
data_folder<-project_folder
library(tidyverse)
#now start the map
library(rgeos)
library(rgdal)
library(maptools)
library(sp)
library(mapproj)
library(ggplot2)
#get test data
mydata<-read_csv("map_data.csv",col_types=list(col_character(),col_double()))
print(mydata)
# shape file came from this link for a digital shape file
# http://www12.statcan.gc.ca/census-recensement/2011/geo/bound-limit/files-fichiers/2016/lpr_000a16a_e.zip
target_url<-"http://www12.statcan.gc.ca/census-recensement/2011/geo/bound-limit/files-fichiers/2016/lpr_000a16a_e.zip"
url_file<-"lpr_000a16a_e.zip"
download_target<-paste0(project_folder,"/",url_file)
download.file(target_url,download_target,mode="wb",quiet=FALSE)
unzip(download_target,overwrite=TRUE,exdir=data_folder)
provincial_shape_file<-gsub(".zip",".shp",download_target)
provincial_shp<-readOGR(dsn=provincial_shape_file,layer="lpr_000a16a_e")
#convert it to the reqired data structure. the id vbl will contain the provincial codes
prov_base_map<-fortify(provincial_shp,region="PRUID")
map_data_1<-merge(prov_base_map,as_data_frame(mydata),by="id")
map1<-ggplot()+
geom_map(data=map_data_1,map=map_data_1,stat="identity",
aes(map_id=id,x=long,y=lat,fill=(pch),group=group),
colour="black",size=0.3)+
coord_map()
print(map1)
The download for the shape file is in the script. The mydata file is shown below
"id","pch"
"10",0.667259786476859
"11",5.63186813186813
"12",2.12053571428572
"13",-0.563697857948142
"24",0.150669774230772
"35",1.15309092428315
"46",0.479282622139765
"47",1.70242950877815
"48",1.84482533036765
"59",1.96197656978394
Here's one way with sf (though I think the ultimate issue is not having the id being identified correctly):
library(sf)
library(httr)
library(tidyverse)
read.csv(text='"id","pch"
"10",0.667259786476859
"11",5.63186813186813
"12",2.12053571428572
"13",-0.563697857948142
"24",0.150669774230772
"35",1.15309092428315
"46",0.479282622139765
"47",1.70242950877815
"48",1.84482533036765
"59",1.96197656978394',
stringsAsFactors=FALSE,
colClasses = c("character", "double")) -> xdf
# cross-platform-friendly d/l with caching built-in
try(httr::GET(
url = "http://www12.statcan.gc.ca/census-recensement/2011/geo/bound-limit/files-fichiers/2016/lpr_000a16a_e.zip",
httr::write_disk("~/Data/lpr_00a16a_e.zip"),
httr::progress()
)) -> res
fils <- unzip("~/Data/lpr_00a16a_e.zip", exdir = "~/Data/lpr")
ca_map <- st_read(grep("shp$", fils, value=TRUE), stringsAsFactors = FALSE)
ca_map <- st_simplify(ca_map, TRUE, 10) # you don't need the coastlines to be that detailed
ca_map <- left_join(ca_map, xdf, by=c("PRUID"="id"))
ggplot(ca_map) +
geom_sf(aes(fill = pch)) +
viridis::scale_fill_viridis(direction=-1, option="magma") +
coord_sf()
As an aside, even though I simplified the shapefile (for faster plotting) I'd hunt around for a light[er]-weight GeoJSON version of the provinces since the one you grabbed has super fine-grained coastlines and you absolutely don't need that for a choropleth.

r geom_map fails with GeoJSON map simplified with gSimplify

I'm constructing world maps with countries color-filled with the (continuous) value depending on a column in a data frame called temp.sp. I want to put several of these maps in a graph. I construct each map using ggplot with geom_map and then construct and display the graphs using multiplot() which uses grid code.
I'm using a GeoJSON map (world <- readOGR(dsn = "ne_50m_admin_0_countries.geojson", layer = "OGRGeoJSON")). The resulting SpatialPolygonsDataFrame is 4.1 Mb and the dataframe that results from worldMap <- broom::tidy(world, region = "iso_a3") has 93391 rows. So when I run multiplot with 4 plot files, it takes a long time.
I thought that I could speed up the printing by simplifying the world map with gSimplify using code like world.simp <- gSimplify(world, tol = .1, topologyPreserve = TRUE). The resulting data frame, worldMap.simp only has 27033 rows but when I use this map I get the error message Error in unit(x, default.units) : 'x' and 'units' must have length > 0.
The error message is generated when I run this code with worldMap.simp. When I use worldMap I have no problems.
gg <- ggplot(temp.sp, aes(map_id = id))
gg <- gg + geom_map(aes(fill = temp.sp$value), map = worldMap.simp, color = "white").
I tried converting temp.sp$value to factor but it made no difference.
To summarize, using a gSimplified map causes the displaying of a graph produced with ggplot and geom_map to fail.
Rather than try to figure out what was going wrong with gSimplify, I found and downloaded a lower resolution map from http://geojson.xyz. The one I'm currently using is
https://d2ad6b4ur7yvpq.cloudfront.net/naturalearth-3.3.0/ne_110m_admin_0_countries.geojson
Note that it has a similar filename, but with 110m instead of 50m.

Resources