rr-sfr-sptmap

Why are my polygons and points from two different sources not rendering in tmap?


I am trying to create a map with a polygon layer and a point in tmap. The replication code and data can be found here.

My code starts like this and creates a map just fine:


################################################################################
### Community Level Maps for NC - Grad Rates by Community Area
### Source: https://toandthrough.uchicago.edu/tool/cps/
################################################################################

### Set wd
setwd("Path/to/Files")

### Load Libraries
library(dplyr)
library(data.table)
library(ggplot2)
library(tmap)
library(leaflet)
library(rgeos)
library(rgdal)
library(sp)
library(raster)
library(stringr)
library(sf)
library(cmapgeo)

### Load Data
data<-fread("data.csv")

################################################################################
### Community Level Edu Outcomes - Attempting to use CMAP
################################################################################

### Create community area
community<-cca_sf
community<-community %>%
  mutate(community=toupper(cca_name))

### Merge in CPS data
community<-community %>%
  left_join(data)

### HS Graduation Map
tm_shape(community) +
  tm_fill("hs_graduation_spr2020",style="jenks",n=5,title = "HS Graduation Rate (Spring 2020)",palette = "Greens") + 
  tm_borders() +
  tm_text("hs_graduation_spr2020",size=.7) +
  tm_credits("Data from To&Through") +
  tm_layout(frame=F)

But then I want to add a point to the map:

### Add in a test point
test_point<-as.data.frame(cbind("lon"=-87.621951,"lat"=41.881722)) # Millenium Park
test_point<-SpatialPointsDataFrame(test_point,test_point,proj4string = CRS("EPSG:3435"))

test_point<-st_as_sf(test_point)

### HS Graduation Map with test point
tm_shape(community) +
  tm_fill("hs_graduation_spr2020",style="jenks",n=5,title = "HS Graduation Rate (Spring 2020)",palette = "Greens") + 
  tm_borders() +
  tm_text("hs_graduation_spr2020",size=.7) +
  tm_credits("Data from To&Through") +
  
  tm_shape(test_point) +
  tm_dots(col="black",size=2) +
  tm_layout(frame=F)

And the point does not render, but will render once I take out the community layer. They have the same CRS projection so I'm not sure what the problem is. Any thoughts?

Thanks!


Solution

  • After a while diving on stackoverflow, I can say that a large number of map plotting issues in R can be broadly answered with : "your objects do not have the right projection". I think this is also the case.

    In my opinion, the error is coming from these lines:

    test_point<-as.data.frame(cbind("lon"=-87.621951,"lat"=41.881722)) # Millenium Park`
    test_point<-SpatialPointsDataFrame(test_point,test_point,proj4string = CRS("EPSG:3435"))`
    

    When assigning the crs, you are using epsg:3435, that is projected with units in feet:

    sf::st_crs(3435)$units
    #> "us-ft"
    

    While "lon"=-87.621951,"lat"=41.881722 are geographic coordinates longitude/latitude:

    https://www.google.com/maps/search/millennium+park+chicago/@41.859633,-87.6353284,13z

    So, your points should be created with epsg:4326 and after that transformed to epsg:3435.

    I modified here the creation of test_point to use epsg:4326, and it seems to be ok so far. Also, I cleaned up a bit your script to reduce the number of libraries that you are loading but not using, and using sf all the way down:

    ################################################################################
    ### Community Level Maps for NC - Grad Rates by Community Area
    ### Source: https://toandthrough.uchicago.edu/tool/cps/
    ################################################################################
    
    ### Set wd
    # setwd("Path/to/Files")
    
    # devtools::install_github("CMAP-REPOS/cmapgeo")
    
    ### Load Libraries
    # Minimum libraries to be used
    library(dplyr)
    #> 
    #> Attaching package: 'dplyr'
    #> The following objects are masked from 'package:stats':
    #> 
    #>     filter, lag
    #> The following objects are masked from 'package:base':
    #> 
    #>     intersect, setdiff, setequal, union
    library(tmap)
    library(sf)
    #> Linking to GEOS 3.8.0, GDAL 3.0.4, PROJ 6.3.1; sf_use_s2() is TRUE
    library(cmapgeo)
    
    ### Load Data
    data <- read.csv("https://raw.githubusercontent.com/Thrive-Data/Using-CMAP/main/data.csv")
    
    ################################################################################
    ### Community Level Edu Outcomes - Attempting to use CMAP
    ################################################################################
    
    ### Create community area
    community <- cca_sf
    community <- community %>%
      mutate(community = toupper(cca_name))
    
    
    ### Merge in CPS data
    community <- community %>%
      left_join(data)
    #> Joining, by = "community"
    
    ### HS Graduation Map
    tm_shape(community) +
      tm_fill("hs_graduation_spr2020", style = "jenks", n = 5, title = "HS Graduation Rate (Spring 2020)", palette = "Greens") +
      tm_borders() +
      tm_text("hs_graduation_spr2020", size = .7) +
      tm_credits("Data from To&Through") +
      tm_layout(frame = F)
    

    
    ### Add in a test point
    test_point <- as.data.frame(cbind("lon" = -87.621951, "lat" = 41.881722)) %>% # Millenium Park
      # To sf
      st_as_sf(coords = c("lon", "lat"), crs = st_crs(4326)) %>%
      # And aligning now to the crs of community
      st_transform(st_crs(community))
    
    ### HS Graduation Map with test point
    tm_shape(community) +
      tm_fill("hs_graduation_spr2020", style = "jenks", n = 5,
              title = "HS Graduation Rate (Spring 2020)", palette = "Greens") +
      tm_borders() +
      tm_text("hs_graduation_spr2020", size = .7) +
      tm_credits("Data from To&Through") +
    
      tm_shape(test_point) +
      tm_dots(col = "red", size = 2) +
      tm_layout(frame = F)
    

    Created on 2022-08-02 by the reprex package (v2.0.1)