rr-leaflet

Select icons or CircleMarkers based on factor variable


I want to use different icons in a leaflet plot in R based on a factor variable in a dataframe. The factor variable might have 100 different levels, but I only have icons for a few levels, maybe 10 or so. If there is an icon I want to use it, else draw CircleMarkers.

I can do this with a for loop:

library(leaflet)

# Some icons
fruits_icons <- iconList(
  apple = makeIcon("apple.png", iconWidth = 20, iconHeight = 20),
  banana = makeIcon("banana.png", iconWidth = 20, iconHeight = 20)
)

# Some data
latitude <- 48 + runif(20)
longitude <- 10 + runif(20)
fruit <- sample(c("banana", "apple", "pear"), 20, replace = TRUE)
df <- data.frame(latitude, longitude, fruit)

map <- leaflet(df) %>% addTiles()

# check if fruit is in names(icons), then use icons, else circles
for(i in seq_len(nrow(df))){
  if(df$fruit[i] %in% names(fruits_icons)){
    map <- map %>% addMarkers(lng = df$longitude[i], 
                              lat = df$latitude[i], 
                              icon = ~fruits_icons[df$fruit[i]])
  } else {
    map <- map %>% addCircleMarkers(lng = df$longitude[i], 
                                    lat = df$latitude[i])
  }
}

map

Is there a better way to do this without the for loop?


Solution

  • You can just subset the data that you want to use in each of the add*() methods

    leaflet() %>% addTiles() %>%
      addMarkers(data = df[df$fruit %in% names(fruits_icons),], 
                 lng = ~longitude, 
                 lat = ~latitude, 
                 icon = ~fruits_icons[fruit]) %>%
      addCircleMarkers(data = df[!df$fruit %in% names(fruits_icons), ],
                       lng = ~longitude,
                       lat = ~latitude)