This package contains a C++ implementation of the RecMap algorithm [1], [2] to draw maps according to given statistical values. These so-called cartograms or value-by-area-maps may be used to visualize any geospatial-related data, e.g., political, economic or public health data. The input consists of a map represented by overlapping rectangles. This map is defined by the following parameters for each map region:

- a tuple of (x, y) values corresponding to the (longitude, latitude) position,
- a tuple of (dx, dy) of expansion along (longitude, latitude),
- and a statistical value z.

The (x, y) coordinates represent the center of the minimal bounding boxes (MBB), The coordinates of the MBB are derived by adding or subtracting the (dx, dy) tuple accordingly. The tuple (dx, dy) also defines the ratio of the map region. The statistical values define the desired area of each map region.

The output is a rectangular cartogram where the map regions are:

- Non-overlapping,
- connected,
- ratio and area of each rectangle correspond to the desired areas,
- rectangles are placed parallel to the axes.

The construction heuristic places the rectangles in a way that important spatial constraints, in particular

- the topology of the pseudo dual graph,
- the relative position of MBB centers.

are tried to be preserved.

The ratios are preserved, and the area of each region corresponds to the as input given statistical value z.

The graphic below depicts a typical example of a rectangular cartogram drawing.

attach the package

`library(recmap)`

look into for documentation

`help(package="recmap") `

`state`

Facts and Figures Dataset```
usa <- data.frame(x = state.center$x,
y = state.center$y,
# make the rectangles overlapping by correcting lines of longitude distance
dx = sqrt(state.area) / 2 / (0.8 * 60 * cos(state.center$y*pi/180)),
dy = sqrt(state.area) / 2 / (0.8 * 60) ,
z = sqrt(state.area),
name = state.name)
```

The rectangles have to overlap to compute the dual graph. This enables to generate valid input having only the (x, y) coordinates of the map region.

```
library(recmap)
op <- par(mfrow = c(1 ,1), mar = c(0, 0, 0, 0), bg = NA)
plot.recmap(M <- usa[!usa$name %in% c("Hawaii", "Alaska"), ],
col.text = 'black', lwd=2)
```

The index order of the input map has an impact to the resulting cartogram. This algorithmic property is caused due to the computation of the dual graph. In [1] a genetic algorithm was applied as metaheuristic. Due to the limited computing resources on the CRAN check systems, we do not use all the potential of the metaheuristic.

Study the examples of the reference manual `?recmapGA`

on how the GA package can be used.

The **topology error** is an indicator of the deviation of the neighborhood relationships. The error is computed by counting the differences between dual graphs or adjacency graphs of map and cartogram

The **relative positions error** measures the angle difference between all region centers.

The output is a `data.frame`

object.

```
Cartogram <- recmap(Map <- usa[!usa$name %in% c("Hawaii", "Alaska"), ])
head(Cartogram)
```

```
## x y dx dy z name dfs.num
## 1 -86.12445 24.40204 3.201992 2.697824 227.17614 Alabama 31
## 2 -123.13242 29.61981 3.939586 3.257613 337.50407 Arizona 38
## 3 -85.30009 39.65352 3.265364 2.683509 230.44305 Arkansas 33
## 4 -131.42392 31.53933 4.341915 3.488740 398.36290 California 37
## 5 -122.00152 23.21422 3.965671 3.095895 322.87304 Colorado 47
## 6 -53.13517 41.31657 1.896954 1.418697 70.77429 Connecticut 19
## topology.error relpos.error relposnh.error
## 1 4 0.2265446 0.5912115
## 2 4 0.2041032 0.7446224
## 3 6 0.4400093 0.8416664
## 4 3 0.1353180 0.1454522
## 5 8 0.5045327 0.9388417
## 6 3 0.1937878 0.4808290
```

```
smp <- c(29, 22, 30, 3, 17, 8, 9, 41, 18, 15, 38, 35, 21, 23, 19, 6, 31, 32, 20,
28, 48, 4, 13, 14, 42, 37, 5, 16, 36 , 43, 25, 33, 12, 7, 39, 44, 2, 47,
45, 46, 24, 10, 1,11 ,40 ,26 ,27 ,34)
op <- par(mfrow = c(1 ,1), mar = c(0, 0, 0, 0), bg = NA)
plot(Cartogram.Area <- recmap(M[smp, ]),
col.text = 'black', lwd = 2)
```

`summary.recmap(M)`

```
## values
## number of map regions 48.00000
## area error 0.13000
## topology error NA
## relative position error NA
## screen filling [in %] 113.77072
## xmin -124.93741
## xmax -66.26565
## ymin 25.35365
## ymax 50.81868
```

`summary(Cartogram.Area)`

```
## values
## number of map regions 48.00000
## area error 0.00000
## topology error 156.00000
## relative position error 0.09000
## screen filling [in %] 39.74965
## xmin -131.88541
## xmax -26.73219
## ymin 17.21867
## ymax 57.88620
```

`state.x77[, 'Population']`

```
op <- par(mfrow = c(1 ,1), mar = c(0, 0, 0, 0), bg = NA)
usa$z <- state.x77[, 'Population']
M <- usa[!usa$name %in% c("Hawaii", "Alaska"), ]
plot(Cartogram.Population <- recmap(M[order(M$x), ]),
col.text = 'black', lwd = 2)
```

```
# index order
smp <- c(20,47,4,40,9,6,32,33,3,10,34,22,2,28,15,12,39,7,42,45,19,13,43,30,24,
25,11,17,37,41,26,29,21,35,8,36,14,16,31,48,46,38,23,18,1,5,44,27)
op <- par(mfrow = c(1 ,1), mar = c(0, 0, 0, 0), bg = NA)
plot(Cartogram.Population <- recmap(M[smp,]), col.text = 'black', lwd = 2)
```

`state.x77[, 'Income']`

```
usa$z <- state.x77[, 'Income']
M <- usa[!usa$name %in% c("Hawaii", "Alaska"), ]
op <- par(mfrow = c(1 ,1), mar = c(0, 0, 0, 0), bg = NA)
plot(Cartogram.Income <- recmap(M[order(M$x),]),
col.text = 'black', lwd = 2)
```

`state.x77[, 'Frost']`

```
usa$z <- state.x77[, 'Frost']
M <- usa[!usa$name %in% c("Hawaii", "Alaska"), ]
op <- par(mfrow = c(1 ,1), mar = c(0, 0, 0, 0), bg = NA)
Frost <- recmapGA(M, seed = 1)
plot(Frost$Cartogram,
col.text = 'black', lwd = 2)
```

`summary(Frost)`

```
## summary of class recmapGA:
## summary of the GA:
## ── Genetic Algorithm ───────────────────
##
## GA settings:
## Type = permutation
## Population size = 480
## Number of generations = 10
## Elitism = 24
## Crossover probability = 0.8
## Mutation probability = 0.25
##
## GA results:
## Iterations = 10
## Fitness function value = 0.1572351
## Solution =
## x1 x2 x3 x4 x5 x6 x7 x8 x9 x10 ... x47 x48
## [1,] 30 3 27 19 20 15 28 17 40 41 25 43
## Map Cartogram
## number of map regions 48.00000 48.00000
## area error 0.30000 0.00000
## topology error NA 156.00000
## relative position error NA 0.13000
## screen filling [in %] 113.77072 34.24012
## xmin -124.93741 -133.14775
## xmax -66.26565 -17.85919
## ymin 25.35365 24.12804
## ymax 50.81868 67.18886
```

More interactive examples using `state.x77`

data are available by running the code snippet below.

```
# Requires to install the suggested packages
# install.packages(c('colorspace', 'maps', 'noncensus', 'shiny'))
library(shiny)
recmap_shiny <- system.file("shiny-examples", package = "recmap")
shiny::runApp(recmap_shiny, display.mode = "normal")
```

Checkerboards provide examples of sets of map regions which do not have ideal cartogram solutions according to Definition 1 [3].

```
op <- par(mar = c(0, 0, 0, 0), mfrow = c(1, 3), bg = NA)
plot(checkerboard8x8 <- checkerboard(8),
col=c('white','white','white','black')[checkerboard8x8$z])
# found by a greedy randomized search
index.greedy <- c(8, 56, 18, 5, 13, 57, 3, 37, 62, 58, 7, 16, 40, 59, 17, 34,
29, 41, 46, 27, 54, 43, 2, 21, 38, 52, 31, 20, 28, 48, 1, 22,
55, 11, 25, 19, 50, 10, 24, 53, 47, 30, 45, 44, 32, 35, 51,
15, 64, 12, 14, 39, 26, 6, 42, 33, 4, 36, 63, 49, 60, 61, 9,
23)
plot(Cartogram.checkerboard8x8.greedy <- recmap(checkerboard8x8[index.greedy,]),
col = c('white','white','white','black')[Cartogram.checkerboard8x8.greedy$z])
# found by a genetic algorithm
index.ga <- c(52, 10, 27, 63, 7, 20, 32, 18, 47, 28, 6, 55, 11, 61, 38, 50, 5,
21, 36, 34, 2, 22, 3, 1, 29, 57, 43, 4, 51, 58, 31, 49, 44, 25,
59, 33, 17, 40, 8, 41, 26, 37, 19, 56, 45, 35, 62, 53, 24, 64,
30, 15, 39, 12, 60, 48, 16, 23, 46, 42, 13, 54, 14, 9)
plot(Cartogram.checkerboard8x8.ga <- recmap(checkerboard8x8[index.ga,]),
col = c('white','white','white','black')[Cartogram.checkerboard8x8.ga$z])
```

The work on RecMap was initiated by understanding the limits of contiguous cartogram drawing [3] and after studying the visualizations drawn by Erwin Raisz [4]. The purpose of the first implementation [1] was a feasibility check on how computer-generated rectangular cartograms with zero area error could look like. The `recmap`

R package on CRAN provides a rectangular cartogram algorithm to be used by any R user. Now, it is easy to generate input (e.g., no complex polygon mesh), the code is maintainable (less than 500 lines of `C++-11`

code), and the algorithm is made robust to the price of not having all features implemented (simplified local placement; no *empty space error*; no MP1 variant yet). Recent research publications on rectangular cartogram drawing include [5], [6], [7], [8]. However, according to a recent publication [9], `recmap`

remains the only rectangular cartogram algorithm that ‘maintains zero cartographic error’.

`sessionInfo()`

```
## R version 4.1.1 (2021-08-10)
## Platform: x86_64-pc-linux-gnu (64-bit)
## Running under: Debian GNU/Linux 11 (bullseye)
##
## Matrix products: default
## BLAS: /usr/lib/x86_64-linux-gnu/blas/libblas.so.3.9.0
## LAPACK: /usr/lib/x86_64-linux-gnu/lapack/liblapack.so.3.9.0
##
## locale:
## [1] LC_CTYPE=en_US.UTF-8 LC_NUMERIC=C
## [3] LC_TIME=en_US.UTF-8 LC_COLLATE=en_US.UTF-8
## [5] LC_MONETARY=en_US.UTF-8 LC_MESSAGES=en_US.UTF-8
## [7] LC_PAPER=en_US.UTF-8 LC_NAME=C
## [9] 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
## [7] base
##
## other attached packages:
## [1] recmap_1.0.11 sp_1.4-5 Rcpp_1.0.7
## [4] GA_3.2.1 iterators_1.0.13 foreach_1.5.1
##
## loaded via a namespace (and not attached):
## [1] knitr_1.34 magrittr_2.0.1 lattice_0.20-44
## [4] R6_2.5.1 rlang_0.4.11 fastmap_1.1.0
## [7] highr_0.9 stringr_1.4.0 tools_4.1.1
## [10] grid_4.1.1 xfun_0.26 cli_3.0.1
## [13] jquerylib_0.1.4 htmltools_0.5.2 yaml_2.2.1
## [16] digest_0.6.27 crayon_1.4.1 sass_0.4.0
## [19] codetools_0.2-18 evaluate_0.14 rmarkdown_2.11
## [22] stringi_1.7.4 compiler_4.1.1 bslib_0.3.0
## [25] jsonlite_1.7.2 tufte_0.10
```

[1] R. Heilmann, D. A. Keim, C. Panse, and M. Sips, “RecMap: Rectangular Map Approximations,” in *10th IEEE Symposium on Information Visualization (InfoVis 2004), 10-12 October 2004, Austin, TX, USA*, 2004, pp. 33–40.

[2] C. Panse, “Rectangular Statistical Cartograms in R: The recmap Package,” *Journal of Statistical Software, Code Snippets*, vol. 86, no. 1, pp. 1–27, 2018.

[3] D. A. Keim, S. C. North, and C. Panse, “CartoDraw: A Fast Algorithm for Generating Contiguous Cartograms,” *IEEE Trans. Vis. Comput. Graph.*, vol. 10, no. 1, pp. 95–110, 2004.

[4] E. Raisz, “The Rectangular Statistical Cartogram,” *Geographical Review.*, vol. 24, no. 2, pp. 292–296, 1934.

[5] M. J. van Kreveld and B. Speckmann, “On rectangular cartograms,” in *Algorithms - ESA 2004, 12th annual european symposium, bergen, norway, september 14-17, 2004, proceedings*, 2004, pp. 724–735.

[6] M. J. van Kreveld and B. Speckmann, “On rectangular cartograms,” *Comput. Geom.*, vol. 37, no. 3, pp. 175–187, 2007.

[7] K. Buchin, B. Speckmann, and S. Verdonschot, “Evolution strategies for optimizing rectangular cartograms,” in *Geographic information science - 7th international conference, giscience 2012, columbus, oh, usa, september 18-21, 2012. Proceedings*, 2012, pp. 29–42.

[8] K. Buchin, D. Eppstein, M. Löffler, M. Nöllenburg, and R. Silveira, “Adjacency-preserving spatial treemaps,” *Computational Geometry*, vol. 7, no. 1, pp. 100–122, 2016.

[9] S. Nusrat and S. Kobourov, “The State of the Art in Cartograms,” in *EuroVis 2016, 18th EG/VGTC Conference on Visualization, 6-10 June 2016, Groningen, the Netherlands*, 2016.