stats_noob
stats_noob

Reputation: 5897

Creating Leaflet Geo-Spatial Plots in R

Recently, I have started learning about the R package "leaflet". This package allows you to identify points on a map provided their latitude and longitude. I created some fake data and I was able to successfully make a leaflet plot (with popup options that display properties of each point):

    library(dplyr)
    library(leaflet)
    
    map_data <- data.frame("Lat" = c(43.6426, 43.6424, 43.6544, 43.6452, 43.6629), "Long" = c(-79.3871, -79.3860, -79.3807, -79.3806,-79.3957 ),
                           "Job" = c("Economist", "Economist", "Teacher", "Teacher", "Lawyer"),
                           "First_Name" = c("John","James", "Jack", "Jason", "Jim"),
                           "Last_Name" = c("Smith","Charles", "Henry", "David", "Robert"),
                           "vehicle" = c("car", "van", "car", "none", "car"))
    
    map_data %>% leaflet() %>% addTiles() %>% addMarkers(clusterOption=markerClusterOptions(), lng = map_data$Long, lat = map_data$Lat, popup = paste("Job", map_data$Job, "<br>", "First_Name:", map_data$First_Name, "<br>", "Last_Name:", map_data$Last_Name, "<br>", "vehicle:", map_data$vehicle, "<br>" )) 

Now, I wanted to take this a few steps further and color code the points based on the "job" of each individual. I found this github tutorial over here that I want to follow: https://poldham.github.io/abs/mapgbif.html

Using the same data I previously created, I tried to re-create a similar plot (slightly modifying it by adding my own popup options). However, when I run my code, I now get an empty map. Can someone please tell me what I am doing wrong? I have attached my code below:

library(dplyr)
library(leaflet)
library(RColorBrewer)

#create map data
map_data <- data.frame("Lati" = c(43.6426, 43.6424, 43.6544, 43.6452, 43.6629), "Longi" = c(-79.3871, -79.3860, -79.3807, -79.3806,-79.3957 ),
"Job" = c("Economist", "Economist", "Teacher", "Teacher", "Lawyer"),
"First_Name" = c("John","James", "Jack", "Jason", "Jim"),
 "Last_Name" = c("Smith","Charles", "Henry", "David", "Robert"),
 "vehicle" = c("car", "van", "car", "none", "car"))


#create initial map
map <- leaflet::leaflet(map_data) %>%
  addTiles() %>%  # Add default OpenStreetMap map tiles
  addMarkers(~Longi, ~Lati, popup = map_data$Job)

#add markers
map <- leaflet(map_data) %>% addTiles() %>%  addCircleMarkers(~Longi,
    ~Lati, popup = map_data$Job, radius = 1, fillOpacity = 0.5, clusterOptions = markerClusterOptions())


map <- leaflet(map_data) %>% addTiles() %>% addCircleMarkers(~Longi, ~Lati,
    popup = map_data$Job, radius = 1, weight = 2, opacity = 0.5, fill = TRUE,
    fillOpacity = 0.2)

#create colors (is it possible to make the colors Red, Blue and Green?)
previewColors(colorFactor("Paired", domain = NULL), LETTERS[1:3])

kingdom <- c("Economist", "Lawyer", "Teacher")

my_palette <- brewer.pal(3, "Paired")

previewColors(colorFactor(my_palette, levels = kingdom), kingdom)

factpal <- colorFactor(my_palette, levels = kingdom)


species_circle <- leaflet(map_data) %>% addTiles() %>% addCircleMarkers(~Longi,
    ~Lati, popup = map_data$Job, radius = 1, weight = 2, opacity = 0.5,
    fill = TRUE, fillOpacity = 0.2, color = ~factpal(kingdom))
species_circle


groups = unique(map_data$Job)

#finalize map
map = leaflet(map_data) %>% addTiles(group = "OpenStreetMap")
for (i in groups) {
    data = map_data[map_data$kingdom == i, ]
    map = map %>% addCircleMarkers(data = data, ~Longi, ~Lati, radius = 1,
        weight = 2, opacity = 0.5, fill = TRUE, fillOpacity = 0.2, color = ~factpal(kingdom),
        group = i)
}
map %>% addLayersControl(overlayGroups = groups, options = layersControlOptions(collapsed = FALSE)

%>%   addTiles() %>%  # Add default OpenStreetMap map tiles
  addMarkers(lng = map_data$Long, lat = map_data$Lat,
             popup = paste("Job", map_data$Job, "<br>",
                           "First_Name:", map_data$First_Name, "<br>",
                           "Last_Name:", map_data$Last_Name, "<br>",  "vehicle:", map_data$vehicle, "<br>" ))

Thanks!

Upvotes: 0

Views: 230

Answers (1)

stefan
stefan

Reputation: 123818

The main issue with your code is that you filter on variable map_data$kingdom (which is no column of map_data) in the for loop instead of on variablr map_data$Job. Hence data is always an empty df and you don't get any markers.

Besides that:

  1. You don't need the for loop
  2. To get the right assigments for colors map ~factpal(Job) on color instead of ~factpal(kingdom).
  3. You don't need to refer to variables in your data with map_data$. Simply use the name of the variable. Leaflet by default will look for these variables in the dataset you provided with leaflet(map_data)

I reduced all the unnecessary code to focus on the main map code. For illustration purposes I increased the radius of the cirleMarkers to 10 and set the opacity to 1.

library(dplyr)
library(leaflet)
library(RColorBrewer)

# create map data
map_data <- data.frame(
  "Lati" = c(43.6426, 43.6424, 43.6544, 43.6452, 43.6629), "Longi" = c(-79.3871, -79.3860, -79.3807, -79.3806, -79.3957),
  "Job" = c("Economist", "Economist", "Teacher", "Teacher", "Lawyer"),
  "First_Name" = c("John", "James", "Jack", "Jason", "Jim"),
  "Last_Name" = c("Smith", "Charles", "Henry", "David", "Robert"),
  "vehicle" = c("car", "van", "car", "none", "car")
)

kingdom <- c("Economist", "Lawyer", "Teacher")
my_palette <- brewer.pal(3, "Paired")
factpal <- colorFactor(my_palette, levels = kingdom)

groups <- unique(map_data$Job)

# finalize map
map <- leaflet(map_data) %>%
  addTiles(group = "OpenStreetMap") %>% 
  addCircleMarkers(~Longi, ~Lati, popup = ~Job,
                   radius = 10, weight = 2, opacity = 1, color = ~factpal(Job),
                   fill = TRUE, fillOpacity = 1, group = ~Job
  )

map %>%
  addLayersControl(overlayGroups = groups, options = layersControlOptions(collapsed = FALSE)) %>%
  addTiles() %>%
  addMarkers(lng = ~Longi, 
             lat = ~Lati, 
             popup = ~paste("Job", Job, "<br>", 
                            "First_Name:", First_Name, "<br>", 
                            "Last_Name:", Last_Name, "<br>", "vehicle:", vehicle, "<br>"))

enter image description here

EDIT To achieve the features you mentioned in your comment you could do:

  1. If you want different colors you can simply pass any color vector to colorFactor, e.g.

    my_palette <- c("red", "green", "blue")
    factpal <- colorFactor(my_palette, levels = kingdom)
    
  2. To remove the pins drop the line starting with addMarkers. In that case you have to move the code for the popup into addCircleMarkers (but be aware that there is already a popup=~Job in addCircleMarkers, i.e. overwrite this one). Another option would be to add group=~Job to addMarkers. Doing so only the pins for checked jobs will appear on the map.

Upvotes: 1

Related Questions