Skip to contents

Beyond traditional cartographic representation functions, geoviz also offers more advanced cartographic transformations.

First, let’s load packages and data.

library(geoviz)
library(sf)

world <- st_read(
  system.file("gpkg/world.gpkg", package = "geoviz"),
  quiet = TRUE
)
afr <- world[world$region == "Africa",]

cities <- st_read(
  system.file("gpkg/cities.gpkg", package = "geoviz"),
  quiet = TRUE
)

Grids

With the viz_gridchoro function, it is possible to aggregate points into regular grids. Several grid types are available and can be selected using the grid parameter. First, there are regular grids in the plane: "square", "diamond", "hexbin", "triangle", and "random". It is also possible to use regular grids on the globe: "h3" and "square_sph".

If the var parameter is specified with an absolute quantitative variable, the function sums the values and assigns them to the grid cells. If var is not specified, the function simply counts the number of points.

Then, to create the choropleth map, you can use exactly the same parameters as in the viz_choro function.

Here is an example of a regular grid on the plane of the map.

viz_create(projection = "EqualEarth", zoomable = T) |>
viz_path(datum = world, fill = "#CCC") |>
viz_gridchoro(data = cities, var = "population", grid = "square") |>
viz_path(data = cities, fill = "black", r = 2) |>
viz_render()

And here is an example of a regular grid on the globe.

viz_create(projection = "Orthographic.rotate([30,-30])",
           zoomable = "versor") |>
viz_outline() |>
viz_path(datum = world, fill = "white", fillOpacity = 0.3) |>
viz_gridchoro(data = cities, var = "population", grid = "h3",
              level = 1, colors = "Reds") |>
viz_path(data = cities, fill = "black", r = 2) |>
viz_render()

If the data are not points but polygons, the values are distributed proportionally to the intersected area. As a result, the computation is much slower.

viz_create(projection = "Mercator", zoomable = T,
           domain = afr, margin = 100) |>
viz_gridchoro(data = afr, var = "pop", step = 50,
              grid = "hexbin", colors = "Oranges",
              stroke = "none") |>
viz_path(datum = afr, fill = "none", stroke = "white") |>
viz_render()

In the previous maps, a stock variable is represented using a color gradient. This is not a major issue since all grid cells have the same size. However, if you want to map a ratio—for example, GDP per capita—you need to specify the numerator and the denominator as follows.

viz_create(projection = "Mercator", zoomable = T,
           domain = afr, margin = 100) |>
viz_gridchoro(data = afr, var = c("gdp", "pop"), step = 50,
              grid = "hexbin", colors = "Blues",
              stroke = "none") |>
viz_path(data = afr, fill = "none", stroke = "white") |>
viz_render()

Heatmaps

Thanks to d3.contourDensity, it is also possible to create smoothed maps in geoviz with the viz_smooth function. d3.contourDensity() is a function from the d3-contour module that computes density contours (isodensity lines) from a set of points. It is the equivalent of a 2D kernel density estimation (KDE). It returns polygons representing areas of equal density.

By varying the bandwidth, thresholds, and cellSize parameters, you can change the level of generalization of the map. With the parameter colors, you can use a palette available in dicopal.

CHN_cities <- cities[cities$iso3 == "CHN", ]

viz_create(domain = CHN_cities, margin = 50) |>
viz_tile(url = "worldimagery") |>
viz_smooth(data = CHN_cities, var = "population") |>
viz_render()

Bertin dots

With the viz_gridprop function, and following exactly the same principles as the viz_gridchoro function, it is possible to aggregate data into regular grid cells and then represent them using proportional symbols. This produces a cartographic representation similar to Bertin-style dot maps.

viz_create(projection = "Mercator", zoomable = T) |>
viz_path(data = afr, fill = "#CCC", fillOpacity = 0.3) |>
viz_gridprop(data = afr, var = "pop", k = 30, step = 40,
             grid = "square", fill = "#38896F", leg_values_round = 0) |>
viz_render()

Dot density map

The viz_dotdensity function allows you to create dot maps in the style of Armand Joseph Frère de Montizon (1830).

The value of the point is calculated automatically and displayed at the bottom left of the map. However, you can choose a value yourself using the dotval parameter.

viz_create(projection = "EqualEarth", zoomable = T) |>
viz_outline() |>
viz_graticule(step = 30, stroke = "white") |>
viz_path(datum = world, fill = "white", fillOpacity = 0.3) |>
viz_dotdensity(data = world, var = "pop", fill = "#38896F") |>
viz_render()

Obviously, this map is not very accurate since the points are randomly distributed within large countries. For a more accurate map, more precise data is needed.