How to add multiple lines label on a Leaflet map

Views
Image credit: Andrew Stutesman on Unsplash

Welcome

I have been teaching the Forecasting and Forensic Analytics course using R programming at Singapore Management University. One of the assignments is to draw a geographic map for data visualization purpose using the package:leaflet. Students are asked to show a single-line text label and a milti-line text popup for markers on a map. Then one student asked how to show multi-line text label as he found the syntax for label and popup is different. So this post is a record for future reference.

Leaftlet map with single line label

Let’s first load the data we will use to draw the map.

mapdata <- read.csv("mapdata.csv")
str(mapdata)
## 'data.frame':    7 obs. of  8 variables:
##  $ conm       : chr  "ROBINSON & CO LTD" "METRO HOLDINGS LTD" "ISETAN (SINGAPORE) LTD" "CK TANG LTD" ...
##  $ BUILDING   : chr  "RAFFLES CITY SHOPPING CENTRE" "NGEE ANN CITY" "ISETAN OFFICE BUILDING" "NIL" ...
##  $ LATITUDE   : num  1.29 1.3 1.29 1.28 1.37 ...
##  $ LONGITUDE  : num  104 104 104 104 104 ...
##  $ start      : int  2003 2003 2004 2006 2003 2010 2010
##  $ end        : int  2008 2018 2018 2009 2008 2018 2018
##  $ highest_rev: num  142.6 73.9 110.5 68.8 99.2 ...
##  $ lowest_rev : num  73.6 28.3 32.5 43.1 45.4 ...

As you can see from the above data frame structure, there are seven observations which represent seven retail companies in Singapore (conm). It also contains their location, including building names (BUILDING) and geographic locations (LATITUDE and LONGITUDE). It also includes their range of revenue (highest_rev and lowest_rev) in a specific period (from start year to end year).

The task is to show the seven companies on a Leaflet map, showing a label with company name and a popup with all other detailed information. Here is the code and map.

library(leaflet)

leaflet() %>%
  addTiles() %>%
  setView(lng = 103.85, lat = 1.3, zoom = 11) %>%
  addMarkers(data = mapdata,
             lng = ~LONGITUDE,
             lat = ~LATITUDE,
             label = ~conm,
             popup = ~paste(conm, "<br>Building:", BUILDING,
                            "<br>Years active:", start, "to", end,
                            "<br>Revenue ($M) from", lowest_rev,
                            "to", highest_rev))

You might have noticed the difference between label and popup. A label will show up when you mouse over the marker, which is the default setting using the Leaflet. If you want to show the label directly, you need to add an option which will be shown later.

A popup will only show up when you click the marker on the map. Popup can display multiple lines easily as shown above. It can also recognize HTML tags such as <br> which will insert a line break and <strong></strong> which will bold the text in between.

However, the same syntax does not work on the label argument.

leaflet() %>%
  addTiles() %>%
  setView(lng = 103.85, lat = 1.3, zoom = 11) %>%
  addMarkers(data = mapdata,
             lng = ~LONGITUDE,
             lat = ~LATITUDE,
             label = ~paste(conm, "<br>Building:", BUILDING),
             popup = ~paste(conm, "<br>Building:", BUILDING,
                            "<br>Years active:", start, "to", end,
                            "<br>Revenue ($M) from", lowest_rev,
                            "to", highest_rev))

As shown above, the label does not show multiple lines properly. It seems the underline engines for label and popup are different. According to this post, the reason is that the developers do not add additional security check on popups.

So how to show multiple lines as label? We find the solution in the Leaflet manual. You need to install a new package called package:htmltools. You have to force it to recognize HTML tags using the HTML() function.

labels <- paste(
  "<strong>", mapdata$conm,
  "</strong><br>Building:", mapdata$BUILDING) %>%
  lapply(htmltools::HTML)

Alternatively, you may also use the sprintf() function from Base R which returns a character vector containing a formatted combination of text and variable values. I think this is better than the paste function.

labels <- sprintf(
  "<strong>%s</strong><br/>Building: %s",
  mapdata$conm, mapdata$BUILDING) %>%
  lapply(htmltools::HTML)

Now we can plot the map and it will show labels with multiple lines text.

leaflet() %>%
  addTiles() %>%
  setView(lng = 103.85, lat = 1.3, zoom = 11) %>%
  addMarkers(data = mapdata,
             lng = ~LONGITUDE,
             lat = ~LATITUDE,
             label = ~labels,
             popup = ~paste(conm, "<br>Building:", BUILDING,
                            "<br>Years active:", start, "to", end,
                            "<br>Revenue ($M) from", lowest_rev,
                            "to", highest_rev))

Do you want to show the label text directly even if you don’t mouse over? Just add an label option of noHide = TRUE.

leaflet() %>%
  addTiles() %>%
  setView(lng = 103.85, lat = 1.3, zoom = 11) %>%
  addMarkers(data = mapdata,
             lng = ~LONGITUDE,
             lat = ~LATITUDE,
             label = ~conm,
             labelOptions = labelOptions(noHide = TRUE),
             popup = ~paste(conm, "<br>Building:", BUILDING,
                            "<br>Years active:", start, "to", end,
                            "<br>Revenue ($M) from", lowest_rev,
                            "to", highest_rev))

Conclusion

This document shows how to draw a map with multiple lines of label using the Leaflet package. This is a reference reading for the Forecasting and Forensic Analytics course at the Singapore Management University. I hope you will find this document useful.

You want to know more? Make an appointment with me at calendly.

image credit: picsum

Wang Jiwei
Wang Jiwei
Associate Professor

My current research/teaching interests include digital transformation and data analytics in accounting.

Related