11  Positions

This chapter focuses on how to move map components, such as legends, titles, scale bars, and insets, freely in the map. They can be placed both inside and outside the map frame – with some being in and some being out (Section 11.1). Moreover, map components can be grouped together, which allows them to be moved and arranged as a single unit (Section 11.2).

To demonstrate the positioning of map components, we use a simple map with the elevation raster data of Slovenia in meters above sea level (m asl) (not shown).

library(terra)
library(tmap)
slo_elev = rast("data/slovenia/slo_elev.tif")
tm = tm_shape(slo_elev) +
    tm_raster()

11.1 Positioning

All of the map components can be positioned in any location in the map frame or outside of it. The positioning is done via the position argument, which can take a variety of values. The most common are:

  • A character vector with two elements, where the first is the horizontal position and the second is the vertical position, e.g., c("left", "top") (Figure 11.1).
  • tm_pos_in(): a function that allows to control the position inside the map frame. The first argument is the horizontal position and the second is the vertical position. E.g., tm_pos_in("left", "top") locates a component in the top left corner of the map frame. This function can also take additional arguments to control the position more precisely, including their justification and alignment.
  • tm_pos_out(): a function that allows the control of the position outside the map frame. For example, tm_pos_out("center", "top") places a component in the center of the top side of the map frame. We are also able to specify the position inside the cell defined by the horizontal and vertical position, e.g., tm_pos_out("left", "center", pos.v = "center").

The following two subsections describe how to position map components inside and outside the map frame.

11.1.1 Inside the map frame

Figure 11.1: Examples of positioning map components inside the map frame.

Map legends, by default, are placed outside of the map frame – that is often expected as it does not overlap with the rest of the map content. However, we can find ourselves in a situation where our spatial data is so sparse that the legend can be placed inside the map, filling a white space. Then, we need to use the position argument of tm_legend().

We may use it either with a vector with two elements, or with the tm_pos_in() function (Figure 11.1). For example, position = c("right", "bottom") or position = tm_pos_in("right", "bottom") are equivalent. The first element of the vector is the horizontal position and the second is the vertical position inside the map frame. These elements can be either in lower case letters, UPPER CASE LETTERS, or numbers between 0 and 1.

Lowercase letters, e.g., "right," "bottom", place the selected map component in the right bottom corner but leave some margin to the map frame (Figure 11.2 (a)).

tm_shape(slo_elev) +
    tm_raster(col.legend = tm_legend(position = c("right", "bottom")))
# same as:
# tm_shape(slo_elev) +
#     tm_raster(col.legend = tm_legend(position = tm_pos_in("right", "bottom")))

Uppercase letters, e.g., "RIGHT," "BOTTOM", also places the map component in the bottom right corner but directly touching the map frame (Figure 11.2 (b)).

tm_shape(slo_elev) +
    tm_raster(col.legend = tm_legend(position = c("RIGHT", "BOTTOM")))

Numbers between 0 and 1, e.g., c(0.8, 0.4) places the map component in the right bottom corner – 0.8 is the horizontal position and 0.4 is the vertical position of the top left corner of the map component in relation to the map frame (Figure 11.2 (c)).

tm_shape(slo_elev) +
    tm_raster(col.legend = tm_legend(position = c(0.8, 0.4)))
(a) with lowercase letters: “right”, “bottom”
(b) with uppercase letters: “RIGHT”, “BOTTOM’”
(c) with numbers: 0.8, 0.4
Figure 11.2: Positioning legends inside the map frame.

There is one important difference between specifying the position with a vector and with the tm_pos_in() function. The latter allows to control the position more precisely with additional arguments – just.h, just.v, align.h, and align.v. The just.h and just.v only work when the position is specified with numbers between 0 and 1, and they arguments control the justification of the map component to that position. Take a look at Figure 11.3. The central map component is based on the default justification, which is just.h = "left" and just.v = "top" – it means that the positioning starts from the top left corner of the map component. However, depending on our needs, we can change the justification to just.h = "right" and just.v = "top" (top right corner) or just.h = "left" and just.v = "center" (left central side of the map component).

Figure 11.3: Examples of justification of map components inside the map frame.

The align.h and align.v arguments are used when many map components are grouped together, which is explained in Section 11.2.

11.1.2 Outside the map frame

In general, there are eight locations for map components outside the map frame – each of them can be specified with tm_pos_out() (Figure 11.4). We may place a map component either on one of the sides of the map frame (e.g., tm_pos_out("center", "top")), or in its corner (e.g., tm_pos_out("left", "top")).

Figure 11.4: Examples of positioning map components outside the map frame.

At the same time, placing a map component outside a map frame brings some additional complexity and possibilities. Now, we can not only put a component in a specified place, but also arrange it in that place. For example, tm_pos_out("center," "top") puts the specified component to the top of the map frame, but it is positioned to the left. What should we do if we want to center it?

The tm_pos_out() has four sets of arguments that control the position of a map component outside the map frame:

  • cell.h and cell.v: the horizontal and vertical position of the map component outside the map frame.
  • pos.h and pos.v: the horizontal and vertical position of the map component inside the cell defined by cell.h and cell.v.
  • just.h and just.v: the justification of the map components in relation to the position of the map component inside the cell – only used when pos.h and pos.v are specified as numbers between 0 and 1.
  • align.h and align.v: the alignment of the components is only used when many components are grouped together (Section 11.2).

Let’s see how these arguments work in practice. The cell.h and cell.v arguments are the first two arguments of the tm_pos_out() function and they define the cell in which the map component are placed (Figure 11.5 (a); Figure 11.5 (b)).

tm_shape(slo_elev) +
    tm_raster(col.legend = tm_legend(position = tm_pos_out("center", "bottom")))
tm_shape(slo_elev) +
    tm_raster(col.legend = tm_legend(position = tm_pos_out("left", "center")))

Then, we may to control the location of the map component inside the cell with pos.h and pos.v arguments. The pos.h argument controls the horizontal position of the map component inside the cell, while the pos.v argument – the vertical position. The former is mostly useful when our legend is on the top of the map frame and the latter is useful when it is on the left or right side of the map frame (Figure 11.5 (c); Figure 11.5 (d)).

tm_shape(slo_elev) +
    tm_raster(col.legend = tm_legend(position = tm_pos_out("center", "bottom", 
                                                           pos.h = "center")))
tm_shape(slo_elev) +
    tm_raster(col.legend = tm_legend(position = tm_pos_out("left", "center", 
                                                           pos.v = "center")))
(a) with cell.h = "center" and cell.v = "bottom"
(b) with cell.h = "left" and cell.v = "center"
(c) with pos.h = "center" in cell (cell.h = "center", cell.v = "bottom")
(d) with pos.v = "center" in cell (cell.h = "left", cell.v = "center")
Figure 11.5: Positioning legends outside the map frame.

11.2 Many components

Various map components can be positioned at the same time – either to different locations or to the same one. For example, we can place a scale bar outside the map frame and a legend inside the map frame (Figure 11.6 (a)).

tm_shape(slo_elev) +
  tm_raster(col.legend = tm_legend(position = c("right", "bottom"))) +
  tm_scalebar(position = tm_pos_out("left", "center"))

Now, you may be wondering what happens if we want to place two (or more) components in the same location. As you can see in Figure 11.6 (b), they are stacked on top of each other inside one frame.

tm_shape(slo_elev) +
  tm_raster(col.legend = tm_legend(position = tm_pos_out("right", "center"))) +
  tm_scalebar(position = tm_pos_out("right", "center"))
(a) in different locations
(b) in the same location
Figure 11.6: Positioning two map components.

The tmap package also has a mechanism to group map components together and then position and organize them as a single unit. This requires two steps:

  1. Specifying the group_id argument in the map component that we want to group together – this should be a unique number or text identifier.
  2. Using the tm_components() function to select which group of map components we want to position together and where.

In the following example, we have three map components – a legend, a scale bar, and credits – and we want to group the scale bar and credits (Figure 11.7 (a)). First, we specify the group_id argument in the map components functions, and then we use the tm_components() function to position them together. Here, the position argument works exactly as we already described in the previous sections, i.e., it can be specified with a vector or with the tm_pos_in() or tm_pos_out() functions.

tm_shape(slo_elev) +
  tm_raster(col.legend = tm_legend(group_id = 1)) +
  tm_scalebar(group_id = 2) +
  tm_credits("My credits", group_id = 2) +
  tm_components(1, position = tm_pos_in("right", "bottom")) +
  tm_components(2, position = tm_pos_in("left", "top"))

The tm_components() function can also be used to customize the arrangement of map components in the same location. For example, we can stack them vertically (stack = "vertical", default) or horizontally (stack = "horizontal") (Figure 11.7 (b)).

tm_shape(slo_elev) +
  tm_raster(col.legend = tm_legend(group_id = 1)) +
  tm_scalebar(group_id = 2) +
  tm_credits("My credits", group_id = 2) +
  tm_components(1, position = tm_pos_in("right", "bottom")) +
  tm_components(2, position = tm_pos_in("left", "top"), stack = "horizontal")
(a) two groups of map components in different locations
(b) two groups of map components in the same location, one stacked horizontally
Figure 11.7: Grouping map components together.

Each additional map component is placed on the bottom of the previous one if they are in the same location. This can be controlled with the z argument of the map component functions – smaller numbers place the component above others.