rr-sfspdep

Plotting graphs from class `nb` - How to change points color?


It is easier to explain what am I trying to do through the following reproducible example:

library(sf)
library(brazilmaps)
library(spdep)

# loading cities map
cities_mg <- brazilmaps::get_brmap(geo        = 'City', 
                                   geo.filter = list(State = 31),
                                   class      = 'sf')

# creating adjacency matrix (neighborhood graph)
nb_mg <- spdep::poly2nb(cities_mg)

# plotting
coords_mg <- st_coordinates(st_centroid(st_geometry(cities_mg)))

par(bg = '#2E2E2E')
plot(nb_mg, coords_mg, pch = 19, cex = .6, lwd = .4, 
     col = '#00C040', points = T)

This piece of code generates the following plot enter image description here

What I would like to do, is coloring the nodes (or vertices) with the same color as the edges. Is it possible?

Thank you in advance.

Session info (for reproducibility) below.

R version 3.6.1 (2019-07-05)
Platform: x86_64-pc-linux-gnu (64-bit)
Running under: Ubuntu 19.04

Matrix products: default
BLAS:   /usr/lib/x86_64-linux-gnu/blas/libblas.so.3.8.0
LAPACK: /usr/lib/x86_64-linux-gnu/lapack/liblapack.so.3.8.0

locale:
 [1] LC_CTYPE=en_US.UTF-8       LC_NUMERIC=C               LC_TIME=en_US.UTF-8        LC_COLLATE=en_US.UTF-8     LC_MONETARY=en_US.UTF-8   
 [6] LC_MESSAGES=en_US.UTF-8    LC_PAPER=en_US.UTF-8       LC_NAME=C                  LC_ADDRESS=C               LC_TELEPHONE=C            
[11] LC_MEASUREMENT=en_US.UTF-8 LC_IDENTIFICATION=C       

attached base packages:
[1] stats     graphics  grDevices utils     datasets  methods   base     

other attached packages:
[1] spdep_1.1-3      spData_0.3.2     sp_1.3-1         brazilmaps_0.1.0 sf_0.8-0        

loaded via a namespace (and not attached):
 [1] gtools_3.8.1       tidyselect_0.2.5   xfun_0.10          purrr_0.3.3        splines_3.6.1      lattice_0.20-38    expm_0.999-4      
 [8] htmltools_0.4.0    XML_3.98-1.20      rlang_0.4.1        pillar_1.4.2       e1071_1.7-2        glue_1.3.1         withr_2.1.2       
[15] DBI_1.0.0          semver_0.2.0       binman_0.1.1       caTools_1.17.1.2   coda_0.19-3        evaluate_0.14      knitr_1.25        
[22] wdman_0.2.4        callr_3.3.2        ps_1.3.0           class_7.3-15       Rcpp_1.0.2         KernSmooth_2.23-16 clipr_0.7.0       
[29] openssl_1.4.1      classInt_0.4-1     gdata_2.18.0       RSelenium_1.7.5    deldir_0.1-23      fs_1.3.1           askpass_1.1       
[36] digest_0.6.22      gmodels_2.18.1     processx_3.4.1     dplyr_0.8.3        grid_3.6.1         tools_3.6.1        bitops_1.0-6      
[43] LearnBayes_2.15.1  magrittr_1.5       tibble_2.1.3       crayon_1.3.4       pkgconfig_2.0.3    whisker_0.4        MASS_7.3-51.4     
[50] Matrix_1.2-17      reprex_0.3.0       rstudioapi_0.10    assertthat_0.2.1   rmarkdown_1.16     R6_2.4.0           boot_1.3-23       
[57] units_0.6-5        nlme_3.1-141       compiler_3.6.1    

Solution

  • Here's a trick. The plot.nb calls points to draw the points, and this is an S3 method. So if we can make it run on an object which we can define a class for, we can make it do anything.

    At the moment it takes a 2-column matrix from st_coordinates, and the plot.nb function takes the two columns and feeds those to points(x,y,...). If we instead construct a 2-column data frame from the matrix:

    coords_mg = data.frame(coords_mg[,1],coords_mg[,2])
    

    then it will still work. If we then give the first column a new class:

    class(coords_mg[,1]) = "adjpts"
    

    then the points(x,y,...) will call the method for adjpts, which we define as this:

    points.adjpts=function(x,y,...){
      points(unclass(x),unclass(y),col="#00c040",pch=19)
    }
    

    Then doing:

    plot(nb_mg, coords_mg, pch = 19, cex = .6, lwd = .4,col = '#00C040', points = T)
    

    does the magic resulting in:

    enter image description here