Failure to establish interactive layers in a Leaflet map data visualization

Hello Everyone,

For the first time, I'm venturing into creating interactive data visualizations. I'm quite excited about the data visualization options that interactive visualizations can provide to my clients.

However, I'm having trouble establishing interactive layer controls in a leaflet map.

I am using as an inspiration map, the example at https://rstudio.github.io/leaflet/showhide.html. On the website, click "Show/Hide Layers along the left side and scroll to " Interactive Layer Display" above the map of earthquakes, as shown in this screen shot:



This map also is included at the end of the html file that can be knitted from the included rmd script. I can't upload the html file output as a pdf because the interactive maps don't translate into a pdf document.

Either in the website map or in the map in the html file, you will see that the layers controls along the right hand side of the earthquake map are interactive. Base layers and importantly, the overlay layers (quakes and outline) appear and disappear when the radio boxes are checked or unchecked.

In my version of the interactive leaflet map using lender data (see the screenshot below), the layer controls for the overlay layers can be checked and unchecked but icons do not disappear and appear.



Due to my inexperience with interactive controls, I'm at a loss to troubleshoot this intelligently. I've played with various changes to the script but I'm not making progress in solving this issue.

I'm wondering if this strategy isn't working (and a little afraid) because my data are fundamentally different (grouped data frame with factor and numeric variables) from the data used by the authors of the quake map (data frame with numerical and integer variables.

I'd appreciate any guidance, education, or suggestions that you might have.

Thanks in advance.

Linda


---
title: "Leaflet_Map_to_Segment_Lenders_by_Geography"
author: "LindaLandon"
date: "8/7/2019"
output: html_document
---

```{r setup, include=FALSE}
knitr::opts_chunk$set(echo = TRUE)

library(dplyr)
library(magrittr)
library(leaflet) # for interactive maps
library(tidyverse)

pagebreak <- function() {
  if(knitr::is_latex_output())
    return("\\newpage")
  else
    return('<div style="page-break-before: always;" />')
}
```

```{r, warning=FALSE,echo=FALSE, message=FALSE, heading_w_markdown}

library(tmap)
library(tmaptools)
library(sf)

# http://bit.ly/31wp4ml
# http://bit.ly/2YIOoc6
# http://bit.ly/2Z7pQJe

# download zip file containing us county shape file (tmap, tmaptools)
download.file("https://www2.census.gov/geo/tiger/GENZ2017/shp/cb_2017_us_county_5m.zip", destfile = "us_counties.zip")
  #unzip
  unzip("us_counties.zip")
#read in shape file (sf)
us_counties <- read_shape("cb_2017_us_county_5m.shp", as.sf = TRUE, stringsAsFactors = FALSE)
```

# The "Almost - But Not Quite - There" Leaflet MAP for Segmenting Lenders' Borrowers by Geography

#### The goal is to provide an interactive html file to the client to allow the client to segment the geographic location of where another lender's borrowers are located. I intend for the client to selectively add or remove borrowers from the map by checking or unchecking boxes. 

#### However, in my version of this code, the overlay group check boxes don't function to add and remove lenders from the map.

#### Longitude and latitutde for borrowers' addresses are given, and the icons occur at the long-lat coordinates for the borrower. 

#### The icon colors indicate which lender provided the loan to the borrower.

`r pagebreak()`

```{r, warning=FALSE,echo=FALSE, message=FALSE}

library(leaflet) # for interactive maps

# http://bit.ly/2YZAhOH
# http://bit.ly/2ZY0qdY

# Read in geocoded data
# The borrowers' addresses are geocoded. Borrower info is not included in "geocode"

geocode <- dplyr::data_frame(Lender = 
    factor(c("LEASE CNSLT CORP","LEASE CNSLT CORP","LEASE CNSLT CORP","LEASE CNSLT CORP",
    "1ST COMMUNITY BANK","JOHN DEERE INDL CREDIT","JOHN DEERE INDL CREDIT",
    "FARM CREDIT SVC","KUBOTA CREDIT CORP USA","KUBOTA CREDIT CORP USA",
    "SOUTHERN MO BANK & TRUST","KUBOTA CREDIT CORP USA","JOHN DEERE INDL CREDIT",
    "FARM CREDIT SVC","CITICAPITAL COMMERCIAL LSG","JOHN DEERE INDL CREDIT",
    "AGRICREDIT ACCEPT LLC","AGCO FIN","JOHN DEERE INDL CREDIT","FARM CREDIT SVC",
    "FARM CREDIT SVC","C N H INDL CAPITAL AMER","JOHN DEERE INDL CREDIT",
    "FARM CREDIT SVC","FARM CREDIT SVC","JOHN DEERE INDL CREDIT","JOHN DEERE INDL CREDIT",
    "KUBOTA CREDIT CORP USA","KUBOTA CREDIT CORP USA","JOHN DEERE INDL CREDIT",
    "KUBOTA CREDIT CORP USA","KUBOTA CREDIT CORP USA","U S BANK","U S BANK","U S BANK",
    "JOHN DEERE INDL CREDIT","1ST NATL BANK","1ST BANK","1ST BANK","JOHN DEERE INDL CREDIT",
    "C N H INDL CAPITAL AMER","JOHN DEERE INDL CREDIT","FARM CREDIT SVC",
    "KUBOTA CREDIT CORP USA","JOHN DEERE INDL CREDIT","BANK STAR OF THE BOOTHEEL",
    "JOHN DEERE INDL CREDIT","JOHN DEERE INDL CREDIT","LEASE CNSLT CORP",
    "SOUTHERN MO BANK & TRUST","SOUTHERN MO BANK & TRUST","SOUTHERN MO BANK & TRUST",
    "SOUTHERN MO BANK & TRUST","SOUTHERN MO BANK & TRUST","SOUTHERN MO BANK & TRUST",
    "SOUTHERN MO BANK & TRUST","SOUTHERN MO BANK & TRUST","SOUTHERN MO BANK & TRUST",
    "JOHN DEERE INDL CREDIT","JOHN DEERE INDL CREDIT","FARM CREDIT SVC",
    "BANK STAR OF THE BOOTHEEL","BANK STAR OF THE BOOTHEEL","BANK STAR OF THE BOOTHEEL",
    "BANK STAR OF THE BOOTHEEL","BANK STAR OF THE BOOTHEEL","BANK STAR OF THE BOOTHEEL",
    "BANK STAR OF THE BOOTHEEL","BANK STAR OF THE BOOTHEEL","BANK STAR OF THE BOOTHEEL",
    "BANK STAR OF THE BOOTHEEL","BANK STAR OF THE BOOTHEEL","C N H INDL CAPITAL AMER",
    "JOHN DEERE INDL CREDIT","JOHN DEERE INDL CREDIT","JOHN DEERE INDL CREDIT",
    "JOHN DEERE INDL CREDIT","AGCO FIN","JOHN DEERE INDL CREDIT","JOHN DEERE INDL CREDIT",
    "U S BANK","C N H INDL CAPITAL AMER","FARM CREDIT SVC","C N H INDL CAPITAL AMER",
    "C N H INDL CAPITAL AMER","JOHN DEERE INDL CREDIT","AGCO FIN","1ST STATE BANK & TRUST",
    "1ST STATE BANK & TRUST","JOHN DEERE INDL CREDIT","PROGRESSIVE FARM CREDIT SVC",
    "BANK STAR OF THE BOOTHEEL","1ST COMMUNITY BANK","1ST COMMUNITY BANK",
    "1ST COMMUNITY BANK","PROGRESSIVE FARM CREDIT SVC","JOHN DEERE INDL CREDIT",
    "JOHN DEERE INDL CREDIT","CITICAPITAL COMMERCIAL LSG","C N H INDL CAPITAL AMER",
    "KUBOTA CREDIT CORP USA","KUBOTA CREDIT CORP USA","LEASE CNSLT CORP",
    "C N H INDL CAPITAL AMER","JOHN DEERE INDL CREDIT","JOHN DEERE INDL CREDIT")),
    long = 
    c(-94.27456,-94.27456,-94.27456,-94.27456,-89.79196,-94.37111,-94.37111,
    -92.20399,-93.98859,-91.94796,-95.53193,-92.66262,-92.66262,-91.8133,
    -92.71902,-93.72647,-92.6015,-92.56674,-92.25091,-93.37044,-93.96622,
    -93.22897,-93.64824,-94.59615,-93.35404,-93.98625,-92.75678,-92.65306,
    -92.65306,-89.66577,-90.44213,-90.44213,-94.54004,-94.54004,-94.54004,
    -92.02807,-91.8997,-91.156,-91.156,-92.84725,-91.81772,-93.31644,-91.32467,
    -94.11608,-92.45053,-94.31402,-92.03817,-91.55717,-94.26523,-90.26736,
    -90.26736,-90.26736,-90.26736,-90.26736,-90.26736,-90.26736,-90.26736,
    -90.26736,-96.13449,-93.39938,-93.11776,-89.7251,-89.7251,-89.7251,-89.7251,
    -89.7251,-89.7251,-89.7251,-89.7251,-89.7251,-89.7251,-89.7251,-94.91495,-90.24603,
    -92.35388,-89.87943,-94.58439,-92.99634,-93.12959,-92.925,-89.45531,-92.96467,
    -94.00131,-89.66703,-89.55216,-90.19742,-91.22804,-89.69537,-89.69537,-91.77336,
    -90.11782,-94.33367,-90.07126,-90.07126,-90.07126,-90.21197,-91.56193,-92.79857,
    -91.48215,-92.21339,-93.12793,-91.41443,-92.12,-94.1507,-93.66071,-93.66071),
    lat =
  c(37.78953,37.78953,37.78953,37.78953,36.04104,38.41959,38.41959,39.07116,40.47055,
    37.98397,40.52908,37.67234,37.67234,40.08035,39.84476,39.06056,39.9818,38.5779,
    38.80903,38.87508,39.27956,40.55038,39.09942,36.56905,39.12317,39.07467,37.4827,
    38.33324,38.33324,37.71015,38.59546,38.59546,37.07221,37.07221,37.07221,39.53807,
    39.16666,38.82014,38.82014,39.61276,40.08884,37.28774,38.90842,38.52177,39.61574,
    38.91264,39.63314,38.72001,40.19307,36.54456,36.54456,36.54456,36.54456,36.54456,
    36.54456,36.54456,36.54456,36.54456,39.21669,39.00088,37.61891,36.17553,36.17553,
    36.17553,36.17553,36.17553,36.17553,36.17553,36.17553,36.17553,36.17553,36.17553,
    39.44226,36.6995,39.78283,37.71869,38.83389,39.80591,39.55287,39.48722,36.88835,
    40.46671,36.94512,36.39381,37.32539,38.85071,39.3362,36.42981,36.42981,38.4506,
    36.04623,40.28232,36.4698,36.4698,36.4698,36.58587,39.63224,39.42085,36.9019,
    40.22177,37.63923,38.06039,36.51022,39.03749,38.3236,38.3236)) 

geocode <- geocode %>% 
group_by(Lender)

# assign colors to markers

getColor <- function(geocode) {
  sapply(geocode$Lender, function(Lender) {
  if(Lender == "JOHN DEERE INDL CREDIT") {
    "red"
  } else if(Lender == "C N H INDL CAPITAL AMER") {
    "green" 
  } else if(Lender == "KUBOTA CREDIT CORP USA") {
    "blue" 
  } else if(Lender == "AGCO FIN") {
    "purple"
  } else if(Lender == "FARM CREDIT SVC") {
    "gray"
  } else if(Lender == "1ST NATL BANK") {
    "orange"
  } else if(Lender == "BANK STAR OF THE BOOTHEEL") {
    "pink"
  } else if(Lender == "PROGRESSIVE FARM CREDIT SVC") {
    "beige"
  } else if(Lender == "1ST COMMUNITY BANK") {
    "lightgray"
  } else if(Lender == "SOUTHERN MO BANK & TRUST") {
    "darkgreen"
  } else if(Lender == "1ST STATE BANK & TRUST") {
    "darkblue"
  } else if(Lender == "AGRICREDIT ACCEPT LLC") {
    "lightgreen"
  } else if(Lender == "BANK OF MTN VIEW") {
    "lightblue"
  } else if(Lender == "CITICAPITAL COMMERCIAL LSG") {
    "lightred"
  } else if(Lender == "LEASE CNSLT CORP") {
    "darkred"
  } else if(Lender == "1ST BANK") {
     "black"
  } else if(Lender == "U S BANK") {
    "black"
  } else {
    "black"
  } })
}

icons <- awesomeIcons(
  icon = 'ios-close',
  iconColor = "cyan",
  library = 'ion',
  markerColor = getColor(geocode)
) 

leaflet(geocode) %>% 
  addTiles() %>%
  addAwesomeMarkers(~long, ~lat, icon=icons, label=~as.character(Lender)) %>% 
  # Layers control
  addLayersControl(
    options = layersControlOptions(collapsed = FALSE),
    overlayGroups = c("LEASE CNSLT CORP","1ST COMMUNITY BANK",
                      "1ST NATL BANK","JOHN DEERE INDL CREDIT",
                      "FARM CREDIT SVC","KUBOTA CREDIT CORP USA",
                      "SOUTHERN MO BANK & TRUST",
                      "CITICAPITAL COMMERCIAL LSG",
                      "AGRICREDIT ACCEPT LLC","AGCO FIN",
                      "C N H INDL CAPITAL AMER","U S BANK",
                      "1ST BANK","BANK STAR OF THE BOOTHEEL",
                      "1ST STATE BANK & TRUST",
                      "PROGRESSIVE FARM CREDIT SVC")
  )
```


`r pagebreak()`

# What I'd Like to See if the Controls Worked

####  My thought is that the client could selectively check lenders by using the control box.

#### Artificially filtered data are shown.

####  Source:  https://rstudio.github.io/leaflet/markers.html

`r pagebreak()`

```{r, warning=FALSE,echo=FALSE, message=FALSE}
library(leaflet)
library(dplyr)

# https://rstudio.github.io/leaflet/markers.html
# https://www.nceas.ucsb.edu/~frazier/RSpatialGuides/colorPaletteCheatsheet.pdf


geocode_reduced <- dplyr::filter(geocode, Lender == "C N H INDL CAPITAL AMER" | Lender == "FARM CREDIT SVC") %>%  
  group_by(Lender)

icons <- awesomeIcons(
  icon = 'ios-close',
  iconColor = "cyan",
  library = 'ion',
  markerColor = getColor(geocode_reduced)
) 

leaflet(geocode_reduced) %>% 
  addTiles() %>%
  addAwesomeMarkers(~long, ~lat, icon=icons, label=~as.character(Lender, "Borrower")) %>% 
  # Layers control
  addLayersControl(
    options = layersControlOptions(collapsed = FALSE),
    overlayGroups = c("LEASE CNSLT CORP","1ST COMMUNITY BANK",
                      "1ST NATL BANK","JOHN DEERE INDL CREDIT",
                      "FARM CREDIT SVC","KUBOTA CREDIT CORP USA",
                      "SOUTHERN MO BANK & TRUST",
                      "CITICAPITAL COMMERCIAL LSG",
                      "AGRICREDIT ACCEPT LLC","AGCO FIN",
                      "C N H INDL CAPITAL AMER","U S BANK",
                      "1ST BANK","BANK STAR OF THE BOOTHEEL",
                      "1ST STATE BANK & TRUST",
                      "PROGRESSIVE FARM CREDIT SVC")
  )

```

`r pagebreak()`

# My Inspiration Maps

## Inspiration map for the controls used to segment the lender

###  Source:  https://rstudio.github.io/leaflet/showhide.html

`r pagebreak()`

```{r, warning=FALSE,echo=FALSE, message=FALSE}

data("quakes")

# Ispiration map url:  https://rstudio.github.io/leaflet/showhide.html

outline <- quakes[chull(quakes$long, quakes$lat),]

map <- leaflet(quakes) %>%
  # Base groups
  addTiles(group = "OSM (default)") %>%
  addProviderTiles(providers$Stamen.Toner, group = "Toner") %>%
  addProviderTiles(providers$Stamen.TonerLite, group = "Toner Lite") %>%
  # Overlay groups
  addCircles(~long, ~lat, ~10^mag/5, stroke = F, group = "Quakes") %>%
  addPolygons(data = outline, lng = ~long, lat = ~lat,
    fill = F, weight = 2, color = "#FFFFCC", group = "Outline") %>%
  # Layers control
  addLayersControl(
    baseGroups = c("OSM (default)", "Toner", "Toner Lite"),
    overlayGroups = c("Quakes", "Outline"),
    options = layersControlOptions(collapsed = FALSE)
  )
map

```

## Inspiration map for the colored icons

###  Source:  https://rstudio.github.io/leaflet/markers.html

```{r, warning=FALSE,echo=FALSE, message=FALSE}

# https://rstudio.github.io/leaflet/markers.html

# first 20 quakes
df.20 <- quakes[1:20,]

getColor <- function(quakes) {
  sapply(quakes$mag, function(mag) {
  if(mag <= 4) {
    "green"
  } else if(mag <= 5) {
    "orange"
  } else {
    "red"
  } })
}

icons <- awesomeIcons(
  icon = 'ios-close',
  iconColor = 'black',
  library = 'ion',
  markerColor = getColor(df.20)
)

leaflet(df.20) %>% addTiles() %>%
  addAwesomeMarkers(~long, ~lat, icon=icons, label=~as.character(mag))

```

1 Like

Linda,

the issue with your code seems to be that you created only a single instance of addAwesomeMarkers() object, and you have not assigned it to any of the groups.

This will not work (as you no doubt have noticed), as the groups you are referring to in your overlayGroup call have not been declared in earlier leaflet code.

What you need to do is filter your dataset to one bank per addMarkers call (or awesome or circle or what not markers) and assign a group value to each.

This group value, once declared, can be then referenced to by an overlayGroups (as a checkbox) or baseGroups (as a radio button) call. But it has to be specified before for the control to work.

I wrote a blog post on Leaflet tips & tricks - including this one - a while back, do have a look at https://www.jla-data.net/eng/leaflet-in-r-tips-and-tricks/ (grouping is an advanced trick, described in the second from last chunk).

3 Likes

@jlacko,

Thanks for your helpful response. I enjoyed your blog post.

I'm working to incorporate your suggestions. There's a learning curve, but I think you made the curve a little less steep.

Linda

Thank you for your kind words; I am glad I could be of service :slight_smile:
J.

1 Like

@jlacko, I wanted to let you know that, using the information in your blog, I was able to create an interactive Leaflet map. Thanks for your help and for sharing your knowledge.

2 Likes

@jlacko, May I presume to ask one more question, please?

I would like to modify the layer control panel to have only one of the layers (alternatively, none of the layers) selected as a default so that my client can start using the map by seeing their customers followed by adding competitors, as opposed to eliminating competitors.

I have been unsuccessful in finding a solution to this.

Do you know if it's possible and how to do that?

Thanks again.

No problem, this is both possible and easy.

You need to pipe function hideGroup() at the end of your leaflet call; it will take as argument a vector of groups to be unchecked (default is to show all).

In this way you can show just one group (by hiding all except one) or none at all (by hiding all).

2 Likes

Thanks!

I'll add that to the code.

Linda

you are welcome :slight_smile:

J.

This topic was automatically closed 7 days after the last reply. New replies are no longer allowed.