My first interactive map with {leaflet}

I have tried creating a map with ggplot2 previously. In this post, I will try to create an interactive map using leaflet package in R.

These are the required packages.

library(tidyverse)
library(tidygeocoder)
library(leaflet)
library(htmltools)

So, I’m going to use a clinics location data in Malaysia. I already uploaded this data tomy GitHub repo. I will skip the explanation for the pre-processing part, but it is the same pre-processing as my previous post.

# Read the data
clinic1m <- read.csv("https://raw.githubusercontent.com/tengku-hanis/clinic-data/main/clinic1m.csv")
clinicDesa <- read.csv("https://raw.githubusercontent.com/tengku-hanis/clinic-data/main/clinicdesa.csv")
Show code for pre-processing
# Get the missing coordinate based on postal codes
clinic1m2 <- 
  clinic1m %>%
  mutate(country = "malaysia") %>% 
  select(name, postcode, country) %>% 
  mutate(postcode = ifelse(nchar(postcode) == 4, paste0(0, postcode), postcode)) %>%
  geocode(postalcode = postcode, country = country, method = "osm")

# Add coordinate from external sources for the still missing coordinates
add_coord <- 
  read.table(header = T, text = "
postal_code    latitude   longitude
16070            6.0334    102.3499
26060            3.6228    102.3926
90700            5.8456    118.0571
26060            3.6228    102.3926")

# Drop clinics with the still missing coordinate
clinic1m2 <- 
  clinic1m2 %>% 
  mutate(lat = ifelse(postcode %in% add_coord$postal_code, add_coord$latitude, lat), 
         long = ifelse(postcode %in% add_coord$postal_code, add_coord$longitude, long)) %>% 
  drop_na() #drop 2 clinic1m

# Bind the 2 data
all_clinic <- 
  clinic1m2 %>% 
  mutate(Type = "1Malaysia") %>% 
  select(name, Type, lat, long) %>% 
  bind_rows(clinicDesa %>% 
              mutate(Type = "Desa", 
                     lat = latitude, 
                     long = longitude) %>% 
              select(name, Type, lat, long)) %>% 
  mutate(name = str_to_title(name))

First, we going to plot the coordinates to see if there is anything strange.

ggplot(all_clinic, aes(long, lat, color = Type)) +
  geom_point() +
  theme_minimal()

So, we are going to remove the two isolated points as seen from the plot.

all_clinic2 <- all_clinic %>% filter(long > 25)

Once we have our data ready, we can supply to leaflet. We can choose the type of map from addProviderTiles(). Some need an api, but the one we choose here does not. We supply the longitude and latitude of our data to addCircleMarkers(), and clusterOptions to cluster our data.

leaflet(all_clinic2) %>% 
  addProviderTiles(providers$Stamen.Watercolor) %>%
  addProviderTiles(providers$Stamen.TerrainLabels) %>%
  addCircleMarkers(~long, ~lat, 
                   clusterOptions = markerClusterOptions())

Next, we can add a label.

labels <- 
  sprintf("<strong>%s</strong>", all_clinic$name) %>% 
  lapply(htmltools::HTML)

Also, we can add a mini map to our map. Here, I change the type of map to a more appropriate one.

leaflet(all_clinic2) %>% 
  addProviderTiles(providers$OpenStreetMap) %>%
  addCircleMarkers(~long, ~lat, popup = ~labels, # popup add the label
                   clusterOptions = markerClusterOptions()) %>% 
    # add a mini map
  addMiniMap(tiles = providers$OpenStreetMap, zoomLevelOffset = -3)

Notice that the coordinates look more accurate as compared to the map I created with ggplot2 previously.

References:

Tengku Muhammad Hanis
Tengku Muhammad Hanis
Lead academic trainer

My research interests include medical statistics and machine learning application.

Related