install.packages(c("sf","mapsf","rnaturalearth","ggplot2","mapiso","mapview"))Getting started with the data
Several packages are used in this tutorial example:
-
sf: manipulation of spatial vector data -
ggplot2: graphical representation -
rnaturalearth: API for downloading NaturalEarth background maps -
mapiso: creation of polygons (contours) from regular grids -
mapsf: thematic cartography -
mapview: interactive mapping
To install them all, execute the following line of code:
Data Import
The database is delivered in two files:
-
geometries.gpkgis a geographic layer containing the geometries drawn by the respondents, associated with variables that characterize them. **1 line = 1 geometry -
survey_anon.csvis a table containing all other variables resulting from the survey. 1 line = 1 respondent.
Each of these files is accompanied by a dictionary of variables in Excel format (geom_dictionnary.xlsx and survey_dictionnary.xlsx).
Respondents database
The main database file can be imported using the R-base function read.csv().
BDR <- read.csv(file = "data/survey.csv",
header = TRUE,
encoding = "UTF8")
# Display column names (variables)
colnames(BDR) [1] "X0001_met_respID_aut" "X0004_met_firact_aut"
[3] "A0101_cad_langua" "A0302_cad_medium_lab_en"
[5] "A0303_cad_enviro_lab_en" "A0405_cad_univer_lab"
[7] "A0405_cad_univer_lab_city" "A0405_cad_univer_lab_country"
[9] "A0406_cad_fields_lab_rec" "A0407_cad_levels_lab_en"
[11] "A0508_cad_gender_lab_en" "A0609_cad_birthc_lab_en"
[13] "A0609_cad_birthc_lab_rec" "A0610_cad_birthy_lab"
[15] "A0611_cad_iddoc1_lab_en" "A0611_cad_iddoc1_lab_rec"
[17] "A0612_cad_iddoc2_lab_en" "A0612_cad_iddoc2_lab_rec"
[19] "A0613_cad_belong_lab_rec" "B0701_lan_langu5_lab_rec"
[21] "B0701_lan_otlan5_lab_rec" "B0702_lan_dailan_lab_rec"
[23] "B0702_lan_otdail_lab_rec" "C0901_mob_living_lab_en"
[25] "C1002_mob_livfam_lab_rec" "C1002_mob_livstu_lab_rec"
[27] "C1002_mob_livpro_lab_rec" "C1002_mob_livoth_lab_rec"
[29] "C1103_mob_travel_lab_en" "C1204_mob_trlist_lab_rec"
[31] "D1301_mob_living_lab_en" "D1402_mob_livpro_lab_rec"
[33] "D1402_mob_livstu_lab_rec" "D1503_mob_travel_lab_en"
[35] "D1604_mob_trlist_lab_rec" "E1801_map_cresid_lab_en"
[37] "F2101_med_topics_lab_en" "F2202_med_intern_lab_en"
[39] "F2202_med_locale_lab_en" "F2202_med_nation_lab_en"
[41] "F2303_med_medias_lab_en" "F2304_med_langue_lab_rec"
[43] "F2304_med_lanoth_lab_rec" "G2501_cul_lgsort_lab_en"
[45] "G2602_cul_lgview_lab_rec" "G2602_cul_otview_lab_rec"
[47] "G2603_cul_lgread_lab_rec" "G2603_cul_otread_lab_rec"
[49] "G2704_cul_orsort_lab_en" "G2805_cul_orread_lab_rec"
[51] "G2805_cul_orview_lab_rec" "H3001_eur_words1_lab_rec"
[53] "H3001_eur_words2_lab_rec" "H3001_eur_words3_lab_rec"
[55] "H3001_eur_words1_lab_en" "H3001_eur_words2_lab_en"
[57] "H3001_eur_words3_lab_en" "H3001_eur_words3_lab_fr"
[59] "H3001_eur_words1_lab_fr" "H3001_eur_words2_lab_fr"
[61] "H3102_eur_images_lab_en" "I3301_cad_educp1_lab_en"
[63] "I3302_cad_educp2_lab_en" "I3403_cad_paysp1_lab_en"
[65] "I3403_cad_paysp1_lab_rec" "I3404_cad_paysp2_lab_en"
[67] "I3404_cad_paysp2_lab_rec" "K3601_met_submit_aut"
Geometries database
Use the sf package to import the geographic layer containing the mental maps.
library(sf)
# List layers of the geopackage file
st_layers("data/geometries.gpkg")Driver: GPKG
Available layers:
layer_name geometry_type features fields crs_name
1 mental_maps Multi Polygon 2744 33 WGS 84 / Pseudo-Mercator
The st_read() function can be used to import geographic data from various formats.
BDG <- st_read(dsn = "data/geometries.gpkg",
layer = "mental_maps")
# Display column names (variables)
colnames(BDG) [1] "ID_geom" "X0001_met_respID_aut"
[3] "Index" "Zoom"
[5] "wkt" "geojson"
[7] "E1902_map_region" "E1903_map_rgname"
[9] "E1903_map_rgname_lab_rec" "E1903_map_rgname_lab_fr"
[11] "E1903_map_rgname_lab_en" "E1903_map_rgname_concept_fr"
[13] "E1903_map_rgname_concept_en" "E1903_map_rgname_scale"
[15] "E1903_map_rgname_type" "E1903_map_rgname_parent1_en"
[17] "E1903_map_rgname_parent2_en" "E1903_map_rgname_parent3_en"
[19] "typ_uni" "typ_mult_uni"
[21] "typ_scale" "typ_over"
[23] "typ_dnk" "typ_HS_del"
[25] "typ_only_text" "geom_carto"
[27] "weight_geom" "weight_geom_tot"
[29] "weight_resp" "weight_resp_tot"
[31] "weight_scale" "weight_scale_tot"
[33] "area" "geom"
All attributes (variables) in this geographic layer relate exclusively to geometries. For cross-referencing with other survey variables, it is necessary to join the two data files.
Joining databases
Each respondent could draw up to 5 different geometries. We will join the respondents database to the geometries database.
The join key common to both databases is the respondent’s identifier: X0001_met_respID_aut..
To join the two databases, use the merge() function.
BDG_merged <- merge(x = BDG,
y = BDR,
by = "X0001_met_respID_aut") # Join fields = respondent idIt is possible to join only a selection of variables from the respondents database, as follows:
BDG_merged <- merge(x = BDG,
y = BDR[c("X0001_met_respID_aut", # Champs de jointure : id répondant
"A0405_cad_univer_lab_country", # Pays de l'université du répondant
"A0508_cad_gender_lab_en", # Genre du répondant en anglais
"A0406_cad_fields_lab_rec", # Champ d'étude en anglais
"A0407_cad_levels_lab_en", # Niveau d'étude en anglais
"A0611_cad_iddoc1_lab_en")], # Papier d'identité 1 en anglais
by = "X0001_met_respID_aut")Descriptive statistics
Contingency table
For a given variable, you can calculate the distribution of individuals per modality with the table() function.
Here is an example with the country of residence variable: A0407_cad_levels_lab_en.
table(BDR$A0407_cad_levels_lab_en)
A-level or equivalent Bachelors degree or equivalent
623 907
Masters degree or equivalent PhD or equivalent
418 46
Prefer not to answer
36
The table() function can be used to calculate a contingency table between two (or more) qualitative variables.
Here is an example with the variables of country of residence and respondent gender:
table(BDR$A0405_cad_univer_lab_country,
BDR$A0508_cad_gender_lab_en)
Female Male Other Prefer not to answer
France Antilles 181 48 2 0
France Metropolitan 420 272 15 13
Germany 347 219 9 7
Ireland 56 40 1 2
Tunisia 124 39 0 1
Turkey 125 104 3 1
Graphical representation
It’s easy to plot a contigency table, either with R-base functions or by using the ggplot2 package.
Contingency table calculation :
freqCountry <- as.data.frame(table(BDR$A0407_cad_levels_lab_en))A. Plot with R-base
barplot(height = freqCountry$Freq,
names = freqCountry$Var1,
main = "Nb. of students per level of studies",
ylab = "Nb. students",
col = "#85c1d3",
las = 2)
B. Plot with ggplot2
library(ggplot2)
ggplot(freqCountry, aes(x = Var1, y = Freq)) +
geom_segment(aes(x = Var1,
xend = Var1,
y = 0,
yend = Freq),
color = "#93C1D5",
lwd = 2) +
geom_point(size = 5,
pch = 19,
color = "#93C1D5") +
ggtitle("Nb. of students per country") +
xlab("Country") +
ylab("Nb. of students") 
Contingency table calculation :
genderCountry <- table(BDR$A0405_cad_univer_lab_country,
BDR$A0508_cad_gender_lab_en)A. Plot with R-base
plot(t(genderCountry),
col = c("#009E7390","#F0E44290", "#0072B290", "#D55E0090", "#CC79A790"),
# col = c("#85c1d3"),
border = "white",
las = 1,
off = 0.5,
main = "Nb. of students per country & gender", # Title
xlab = "Gender", # Axe x title
ylab = "Country")
B. Plot with ggplot2
With the ggplot2 package and the ggmosaic extension, you can represent a contingency table without first calculating it.
library(ggmosaic)
ggplot(data = BDR) +
geom_mosaic(aes(x = product(A0405_cad_univer_lab_country,
A0508_cad_gender_lab_en),
fill= A0405_cad_univer_lab_country)) +
ggtitle("Nb. of students per country & gender") +
xlab("Gender") +
ylab("Country") +
theme(legend.position = "none") 
Cartography
As part of the ANR-DFG IMAGEUN project, several cartographic processes were carried out on the respondents’ mental maps. Below, we explain how to manipulate and map these geographic data (vector polygons) with R.
We begin by selecting the geometries that can be used for the cartography
BDG_carto <- BDG_merged[BDG_merged$geom_carto == TRUE,]Retrieving a base map
The rnaturalearth package enables us to retrieve the map of the world as a vector layer.
library(rnaturalearth)
world <- ne_download(scale = 110,
category = "cultural",
returnclass = "sf")
# Plotting base map
plot(st_geometry(world))
To use this base map as a cover layer for the mental maps, it is necessary to harmonize the map projection used (WGS84 / Pseudo Mercator).
# Reprojection of the base map in "EPSG:3857"
world <- st_transform(world, crs = st_crs(BDG_carto))Plotting the mental maps
First, select the geometry with its identifier. For example :
# Select geometry with ID "GEOM1564"
BDG_plot <- BDG_carto[BDG_carto$ID_geom %in% "GEOM1564", ]As with any sf object (geographic layer), it is then very simple to display the geometry on the world base map using the plot() function, or in a more sophisticated way using the mapsf thematic cartography package.
# Plot the geometry to define map bbox
plot(st_geometry(BDG_plot))
# Plot the world base map
plot(st_geometry(world),
col = "#cccccc",
border = "white",
add = TRUE)
# Plot the geometry
plot(st_geometry(BDG_plot),
col = "#85c1d350",
border = "#85c1d3",
lwd = 2,
add = TRUE)It’s also easy to add information to the mental map, for example :
# Title with respondent ID and geometry ID
title(paste0(BDG_plot$X0001_met_respID_aut, " - ", BDG_plot$ID_geom),
adj = 0)
# Country of residence
mtext(paste0("Country : ", BDG_plot$A0405_cad_univer_lab_country),
side = 3, adj = 0)
# Word associated with the geometry
mtext(text = paste0("Word : ", BDG_plot$E1903_map_rgname),
side = 3, adj = 0, line = -1)
# Traduction of the word associated with the geometry
mtext(text = paste0("trad : ", BDG_plot$E1903_map_rgname_lab_en),
side = 3, adj = 0, line = -2, font = 3)
library(mapsf)
# Intinializing the map bounding box
mf_init(BDG_plot)
# Plot world base map
mf_map(world, border = "white",
col = "gray90", lwd = 2,
add = TRUE)
# Plot mental map
mf_map(BDG_plot, col = "#85c1d350",
border = "#85c1d3", lwd = 2,
add = TRUE)
# Add other key elements to the map
mf_layout(title = paste0(BDG_plot$X0001_met_respID_aut, " - ", BDG_plot$ID_geom),
credits = "Sources : ANR - DFG IMAGEUN (2020-2024) - Students Database",
arrow = TRUE,
scale = TRUE,
frame = TRUE)
# Country of residency
mtext(paste0("Country : ", BDG_plot$A0405_cad_univer_lab_country),
side = 3, adj = 0, line = -0.5)
# Word associated with geometry
mtext(text = paste0("Word : ", BDG_plot$E1903_map_rgname),
side = 3, adj = 0, line = -1.5)
# Traduction od the word associated with geometry
mtext(text = paste0("trad : ", BDG_plot$E1903_map_rgname_lab_en),
side = 3, adj = 0, line = -2.5, font = 3)
The process is similar for displaying multiple geometries on the same map. The mapview library can also be used to quickly display geometries interactively.
First, we select all the geometries drawn by the same respondent. Then, for better map legibility (and interactivity), we order the geometries according to their surface area.
# Select geometries of respondent "9kb8mxs7zfp6"
BDG_plot <- BDG_carto[BDG_carto$X0001_met_respID_aut %in% "9kb8mxs7zfp6", ]
# Order geometries from largest to smallest
BDG_plot <- BDG_plot[order(BDG_plot$area, decreasing = TRUE), ]mf_init(BDG_plot)
mf_map(world, border = "white",
col = "gray90", lwd = 2,
add = TRUE)
mf_map(BDG_plot, col = "#85c1d350",
border = "#85c1d3", lwd = 2,
add = TRUE)
mf_layout(title = unique(BDG_plot$X0001_met_respID_aut),
credits = "Sources : ANR - DFG IMAGEUN (2020-2024) - Students Database",
arrow = TRUE,
scale = TRUE,
frame = TRUE)
mtext(paste0("Country : ", BDG_plot$A0405_cad_univer_lab_country),
side = 3, adj = 0, line = -0.5)
mtext(paste0(BDG_plot$ID_geom, ": ",
BDG_plot$E1903_map_rgname,
collapse = "\n"),
side = 3, adj = 0, line = -4, cex = .8)
library(mapview)
mapview(BDG_plot, zcol = "E1903_map_rgname",
layer.name = paste0(BDG_plot$X0001_met_respID_aut[1], " (",
BDG_plot$A0405_cad_univer_lab_country[1], ") "))Construction of regular grids
The areas drawn by respondents can easily be aggregated (or summed) to produce maps that “summarize” the imaginaries of a group of respondents.
This section describes how to create these aggregated cartographic representations.
Two types of representation are shawn
- Addition (cumulation) of drawn areas.
- Addition (cumulation) of drawn area limits
In both cases, the “aggregation” method is the same: surfaces (polygons) or perimeters (polylines) intersect with a grid. The result is a regular grid in which the value of each tile equals the number of intersections detected. This provides continuous information on the areas included or excluded by the mental maps drawn.
We construct two types of grid.
- A classic vector regular grid (tiles)**, intersected by zone boundaries (polylines).
- A regular vector grid of points**, intersected by surfaces (polygons).
The st_make_grid() function in the sf package is used to construct a regular vector grid. In this case, we are building a 100 square kilometers grid.
# Vector grid creation - sfc object
gridPolyg <- st_make_grid(x = world,
cellsize = 100000,
square = TRUE,
what = "polygons")
# Add an attribute (identifier) to the sfc object (= sf object)
gridPolyg <- st_sf(ID = 1:length(gridPolyg ), geom = gridPolyg )Here is an extract of the vector grid, on a reduced area (Turkey):

The st_make_grid() function can also be used to construct a regular grid of points.
# Vector grid creation - sfc object
gridCenters <- st_make_grid(x = world,
cellsize = 100000,
square = TRUE,
what = "centers")
# Add an attribute (identifier) to the sfc object (= sf object)
gridCenters <- st_sf(ID = 1:length(gridCenters), geom = gridCenters)Here is an extract of the vector grid, on a reduced area (Turkey):

Grids and Mental Maps
Before making the geometric intersections, the first step is to select a corpus of mental maps. We start by extracting all the drawn areas specific to the map
BDG_carto <- BDG_merged[BDG_merged$geom_carto == TRUE,]For this demonstration, we then select all the geometries drawn by the students surveyed in Turkey.
BDG_sub <- BDG_carto[BDG_carto$A0405_cad_univer_lab_country %in% "Turkey", ]We then intersect the set of selected polygons with the grids using the st_intersects() function. The number of intersections detected for each grid tile is stored in the “count” attribute using the lengths() function.
We detect the intersections of the drawn polygons with the regular point grid using the st_intersects() function.
# Grid - polygon intersection calculation
result_intersection <- st_intersects(x = gridCenters,
y = BDG_sub,
sparse = TRUE)
# Add the number of detected intersections in the "count" attribute
gridCenters$count <- lengths(result_intersection) We then calculate the proportion of intersection of each point with respect to the set of polygons drawn.
gridCenters$pct <- gridCenters$count / nrow(BDG_sub) * 100All that remains is to replace the values “0” with “NA”.
gridCenters$pct[gridCenters$pct == 0] <- NAFirst, we transform the drawn polygons into polylines. This allows only the contour of the demarcated areas to be taken into account and not their surface. To do this, we use the function st_cast().
BDG_sub_2 <- st_cast(BDG_sub, to = "MULTILINESTRING")We detect the intersections of the drawn contours (polylines) with the grid using the st_intersects() function.
# Calculation of grid - polyline intersections
result_inter_polyligne <- st_intersects(x = gridPolyg,
y = BDG_sub_2,
sparse = TRUE)
# Add the number of detected intersections in the "count" attribute
gridPolyg$count <- lengths(result_inter_polyligne) We then calculate the percentage of intersection of each tile with respect to the set of polylines drawn.
gridPolyg$pct <- gridPolyg$count / nrow(BDG_sub_2) * 100Then we replace the values “0” with “NA”.
gridPolyg$pct[gridPolyg$pct == 0] <- NAFinally, we extract the centroids of the tiles from the vector grid. This allows you to retrieve a regular grid of points.
gridPolyg_pts <- st_centroid(gridPolyg)Creating Isobands
From the regular grids of points and their count attribute which contains the number of intersections detected for each point of the grid, we can construct polygon contours that group the points according to the value of this attribute (isobands).
The construction of isobands is based on discretization in order to determine classes. In this example, we opt for a discretization by equal amplitudes, but a more in-depth study on the statistical distribution can be carried out to choose a more adequate discretization.
To calculate class bounds, we use the mf_get_break() of the mapsf package. The construction of the isobands is then carried out with the mapiso() function of the package of the same name.
library(mapsf)
# discretization by equal amplitudes
discr <- mf_get_breaks(gridCenters$pct, breaks = "equal")Isobands construction :
library(mapiso)
iso_surface <- mapiso(x = gridCenters,
var = "pct",
breaks = discr)Plot of the result (sf object, polygons):
mf_map(iso_surface)
library(mapsf)
# discretization by equal amplitudes
discr2 <- mf_get_breaks(gridPolyg_pts$pct, breaks = "equal")Isobands construction
library(mapiso)
iso_limites <- mapiso(x = gridPolyg_pts,
var = "pct",
breaks = discr2)Plot of the result (sf object, polygons):
mf_map(iso_limites)
Cartography of the results
First, we define the geographical bounding box of the area of the world that we want to represent on the map. For this, we use the st_bbox() function.
bbox <- st_bbox(c(xmin = -4200000,
ymin = 2500000,
xmax = 8450000,
ymax = 10000000),
crs = st_crs(3857))
# Transformation of the bbox into an sfc object
bbox <- st_as_sfc(bbox) The locator() function allows you to retrieve geographical coordinates interactively in the graphics window. In our example, we use it to place the text element that informs about the number of students and mapped geometries. To do this, display a basemap and then run the locator() function. All you have to do is click in the graphics window and the coordinates of the selected point are returned to the console.
mf_map(world)
# One click (n = 1)
locator(n = 1)All that remains is to map the regions drawn by the Turkish students.

mapsf
# Initializing the bounding box
mf_map(bbox, col = NA, border = NA)
# Add base map
mf_map(world,
border = "lightblue",
col = "gray90",
lwd = 0.5,
add = TRUE)
# Cartography of the intersections
mf_map(x = iso_surface,
var = "isomin",
type = "choro",
breaks = discr,
border = NA,
pal = "Rocket",
alpha = 0.6,
leg_pos = "left",
leg_title = "Prevalence rate (%) of\nsurface drawings",
leg_val_rnd = 1,
add = TRUE)
# Overlaying the countries
mf_map(world,
border = "lightblue",
col = NA,
lwd = 0.2,
add = TRUE)
# Plot the additionnal text
text(x = 7100000,
y = 9986523,
cex = .8,
labels = paste0(length(unique(BDG_sub$X0001_met_respID_aut)), " respondents",
"\n", nrow(BDG_sub), " draws"))
# Finale key elements
mf_layout(
title = "Turkish students' sense of belonging (2022)",
credits = "Authors : Elina Marveaux, Hugues Pecout\nSources : ANR - DFG IMAGEUN (2020-2024) - Students Database",
arrow = FALSE,
scale = FALSE,
frame = TRUE)
mf_arrow(pos = "topright")

mapsf
# Initializing the bounding box
mf_map(bbox, col = NA, border = NA)
# Add base map
mf_map(world,
border = "lightblue",
col = "gray90",
lwd = 0.5,
add = TRUE)
# Cartograpy of the intersections
mf_map(x = iso_limites,
var = "isomin",
type = "choro",
breaks = discr2,
border = NA,
pal = "Rocket",
alpha = 0.6,
leg_pos = "left",
leg_title = "Prevalence rate (%) of\ndelimitation drawings",
leg_val_rnd = 1,
add = TRUE)
# Overlaying the countries
mf_map(world,
border = "lightblue",
col = NA,
lwd = 0.2,
add = TRUE)
# Plot the additionnal text
text(x = 7100000,
y = 9986523,
cex = .8,
labels = paste0(length(unique(BDG_sub$X0001_met_respID_aut)), " respondents",
"\n", nrow(BDG_sub), " draws"))
# Add final key elements
mf_layout(
title = "Turkish students' sense of belonging (2022)",
credits = "Authors : Elina Marveaux, Hugues Pecout\nSources : ANR - DFG IMAGEUN (2020-2024) - Students Database",
arrow = FALSE,
scale = FALSE,
frame = TRUE)
mf_arrow(pos = "topright")
Session informations
R version 4.5.3 (2026-03-11 ucrt)
Platform: x86_64-w64-mingw32/x64
Running under: Windows 11 x64 (build 26200)
Matrix products: default
LAPACK version 3.12.1
locale:
[1] LC_COLLATE=French_France.utf8 LC_CTYPE=French_France.utf8
[3] LC_MONETARY=French_France.utf8 LC_NUMERIC=C
[5] LC_TIME=French_France.utf8
time zone: Europe/Paris
tzcode source: internal
attached base packages:
[1] stats graphics grDevices utils datasets methods base
other attached packages:
[1] ggmosaic_0.4.0 rnaturalearth_1.2.0 ggplot2_4.0.3.9000
[4] mapview_2.11.4 mapsf_1.2.0 mapiso_0.3.0
[7] terra_1.9-11 sf_1.1-0 readODS_2.3.5
[10] readxl_1.4.5 dplyr_1.2.1 kableExtra_1.4.0
loaded via a namespace (and not attached):
[1] tidyselect_1.2.1 viridisLite_0.4.3 farver_2.1.2
[4] S7_0.2.2 fastmap_1.2.0 lazyeval_0.2.3
[7] leaflet_2.2.3 digest_0.6.39 lifecycle_1.0.5
[10] magrittr_2.0.5 compiler_4.5.3 rlang_1.2.0
[13] tools_4.5.3 leafpop_0.1.0 yaml_2.3.12
[16] data.table_1.18.2.1 knitr_1.51 brew_1.0-10
[19] htmlwidgets_1.6.4 sp_2.2-1 classInt_0.4-11
[22] plyr_1.8.9 xml2_1.5.2 RColorBrewer_1.1-3
[25] KernSmooth_2.23-26 minty_0.0.6 withr_3.0.2
[28] purrr_1.2.2 productplots_0.1.2 grid_4.5.3
[31] stats4_4.5.3 e1071_1.7-17 leafem_0.2.5
[34] scales_1.4.0 isoband_0.3.0 cli_3.6.6
[37] rmarkdown_2.31 generics_0.1.4 otel_0.2.0
[40] rstudioapi_0.18.0 httr_1.4.8 tzdb_0.5.0
[43] DBI_1.3.0 proxy_0.4-29 stringr_1.6.0
[46] s2_1.1.9 cellranger_1.1.0 base64enc_0.1-6
[49] vctrs_0.7.3 jsonlite_2.0.0 ggrepel_0.9.8
[52] systemfonts_1.3.2 crosstalk_1.2.2 maplegend_0.6.3
[55] plotly_4.12.0 jquerylib_0.1.4 tidyr_1.3.2
[58] units_1.0-1 glue_1.8.1 leaflet.providers_3.0.0
[61] codetools_0.2-20 stringi_1.8.7 gtable_0.3.6
[64] raster_3.6-32 tibble_3.3.1 pillar_1.11.1
[67] htmltools_0.5.9 satellite_1.0.6 R6_2.6.1
[70] wk_0.9.5 textshaping_1.0.5 evaluate_1.0.5
[73] lattice_0.22-9 png_0.1-9 class_7.3-23
[76] uuid_1.2-2 Rcpp_1.1.1-1.1 zip_2.3.3
[79] svglite_2.2.2 xfun_0.57 pkgconfig_2.0.3
