rannotationsr-sftmapr-stars

How to annotate dataframe to tmap panels in R?


I am trying to add mean and SD to panel plot created using tmap R package. But each panel contains all the annotations overlapped. Now how can I have single annotations per panel? Here is a minimal reproducible code

library(tmap)
library(stars)
library(terra)

#Read some data
tif = system.file("tif/L7_ETMs.tif", package = "stars")
x = terra::rast(tif)

# Summarize data (one summary per raster layer)
summ <- x |> 
  as.data.frame() |> 
  pivot_longer(everything()) |> 
  group_by(name) |> 
  summarise(Mean = mean(value, na.rm = TRUE), 
            SD = sd(value, na.rm = TRUE)) %>% 
  mutate(across(c(Mean, SD), ~round(., 3))) %>% 
  mutate(lab = paste0("Mean = ", Mean, "\nSD = ", SD)) %>% 
  dplyr::select(name, lab)

# Add coordinates for bottom-left placement
bbox <- st_bbox(x)
annotations <- summ %>%
  mutate(
    x = bbox["xmin"] + 0.05 * (bbox["xmax"] - bbox["xmin"]), # Slightly offset from xmin
    y = bbox["ymin"] + 0.1 * (bbox["ymax"] - bbox["ymin"])  # Slightly offset from ymin
  )

# Convert annotations to sf object
annotations_sf <- st_as_sf(annotations, coords = c("x", "y"), crs = st_crs(x))

#Plot it using tmap r package
map <- tm_shape(x) + 
  tm_raster(style="quantile") + 
  tm_facets(nrow = 3) +
  tm_layout(panel.labels = names(x), attr.outside = T, 
            attr.outside.position = "bottom", attr.just = "right",
            legend.outside = T, legend.outside.position = "right",
            legend.position = c("left", "top"),
            legend.text.size = 0.8, legend.title.size = 0.9,
            legend.format = list(digits = 2, text.separator = "-"))+
  tm_compass(position = c("left", "top"))+
  tm_scale_bar(text.size = 1, position = c("RIGHT", "top"))

# Add annotations
map +
  tm_shape(annotations_sf) +
  tm_text("lab", xmod = 0.05, ymod = -0.05, col = "black", just = "left", size = 1)

enter image description here


Solution

  • tm_shape(x) + 
        tm_raster(col.scale = tm_scale_intervals(style="quantile"),
                  col.legend = tm_legend("")) +
        tm_credits(text= annotations_sf$lab, 
                   position=c("left", "bottom"), 
                   col = "black", 
                   just = "left", 
                   size = 1, 
                   bg = TRUE, 
                   bg.alpha = 0.8, 
                   bg.color = "white")+
        tm_facets(nrow=3)+
        tm_compass()+
        tm_scalebar() +
        tm_components(group_id = c("tm_compass", "tm_scalebar"), position = tm_pos_out("center", "bottom", align.v = "bottom"), stack = "horizontal")
    

    enter image description here

    tmap version 4.2 has several features to get this done: credits text is a text component, just like tm_title. Furthermore tm_components is added to control the position of components more intuitively. See online documentation.