tmap icon indicating copy to clipboard operation
tmap copied to clipboard

Adding continuous raster legend when raster contains only NA

Open johnbaums opened this issue 1 year ago • 1 comments

Is it possible to force a continuous raster legend to display when the raster layer contains no non-NA values? Or else to manually add a continuous raster legend?

Consider the following example, where a list of tmap objects describes a temporally varying attribute. Note that in the first time step, the entire raster has value NA - this results in a map with no legend. For animation, and even just for consistency of map layout, having a consistent legend is obviously important.

One workaround is to give one cell a value, e.g. with r0[1] <- 0, but I would prefer not to modify cell values.

library(tmap)
#> 
#> Attaching package: 'tmap'
#> The following object is masked from 'package:datasets':
#> 
#>     rivers
library(terra)
#> terra 1.7.78
r1 <- setNames(rast(land)[[4]], "t1")
r0 <- setNames(init(r1, NA), "t0")
r2 <- setNames(r1 * 1.3, "t2")
r <- list(r0, r1, r2)
zlim <- range(sapply(r, global, "range", na.rm = TRUE), na.rm = TRUE)

L <- lapply(r, function(x) {
  tm_shape(x) + 
    tm_raster(
      col.scale = tm_scale_continuous(values = terrain.colors(9), limits = zlim), 
      col.legend = tm_legend(title = "Elevation")
    ) +
    tm_shape(World) +
    tm_polygons(fill = NA) +
    tm_title(names(x))
})

L
#> [[1]]

#> 
#> [[2]]

#> 
#> [[3]]

Created on 2024-09-24 with reprex v2.1.1

Session info
sessionInfo()
#> R version 4.4.1 (2024-06-14)
#> Platform: x86_64-apple-darwin20
#> Running under: macOS Sonoma 14.6.1
#> 
#> Matrix products: default
#> BLAS:   /Library/Frameworks/R.framework/Versions/4.4-x86_64/Resources/lib/libRblas.0.dylib 
#> LAPACK: /Library/Frameworks/R.framework/Versions/4.4-x86_64/Resources/lib/libRlapack.dylib;  LAPACK version 3.12.0
#> 
#> attached base packages:
#> [1] stats     graphics  grDevices utils     datasets  methods   base     
#> 
#> other attached packages:
#> [1] terra_1.7-78   tmap_3.99.9002
#> 
#> loaded via a namespace (and not attached):
#>  [1] s2_1.1.7                xml2_1.3.6              class_7.3-22           
#>  [4] lwgeom_0.2-14           KernSmooth_2.23-24      lattice_0.22-6         
#>  [7] digest_0.6.37           magrittr_2.0.3          evaluate_1.0.0         
#> [10] grid_4.4.1              RColorBrewer_1.1-3      fastmap_1.2.0          
#> [13] e1071_1.7-16            leafsync_0.1.0          DBI_1.2.3              
#> [16] colorblindcheck_1.0.2   crosstalk_1.2.1         viridisLite_0.4.2      
#> [19] cols4all_0.7-1          XML_3.99-0.17           codetools_0.2-20       
#> [22] abind_1.4-8             cli_3.6.3               rlang_1.1.4            
#> [25] units_0.8-5             tmaptools_3.1-1         reprex_2.1.1           
#> [28] base64enc_0.1-3         withr_3.0.1             yaml_2.3.10            
#> [31] leaflegend_1.2.1        tools_4.4.1             raster_3.6-26          
#> [34] parallel_4.4.1          colorspace_2.1-1        spacesXYZ_1.3-0        
#> [37] widgetframe_0.3.1       curl_5.2.2              R6_2.5.1               
#> [40] png_0.1-8               proxy_0.4-27            lifecycle_1.0.4        
#> [43] classInt_0.4-10         leaflet_2.2.2           leaflet.providers_2.0.0
#> [46] fs_1.6.4                htmlwidgets_1.6.4       data.table_1.16.0      
#> [49] glue_1.7.0              Rcpp_1.0.13             sf_1.0-17              
#> [52] highr_0.11              xfun_0.47               knitr_1.48             
#> [55] dichromat_2.0-0.1       htmltools_0.5.8.1       rmarkdown_2.28         
#> [58] leafem_0.2.3            wk_0.9.3                compiler_4.4.1         
#> [61] sp_2.1-4                stars_0.6-6

johnbaums avatar Sep 24 '24 02:09 johnbaums

Thx @johnbaums

This was a bug that now has been fixed: when the user provides a tm_scale function for a layer with all NA's, it will now show a legend, provided the essential information is there (limits for tm_scale_continuous and breaks for tm_scale_intervals).

However, you can make these series of plots in one go:

rs = c(r0, r1, r2)

tm_shape(rs) + 
  tm_raster(
  col.scale = tm_scale_continuous(values = terrain.colors(9), limits = zlim), 
  col.legend = tm_legend(title = "Elevation")
  ) +
  tm_shape(World) +
  tm_polygons(fill = NA) +
  tm_facets_pagewise()

The only current limitation is that is uses panels rather than outside titles. But that is for another issue;-)

mtennekes avatar Sep 25 '24 18:09 mtennekes