1

How I do a general function to insert the colors of the clusters? I used the leaflet package to generate the map. The way I did it was "if else", it worked, but if for example, I have 15 clusters, I will have many "if else". Can anybody help me ?? In addition, if possible I would like to put legend of the clusters on my map as well. My executable code is below:

library(leaflet)
library(geosphere)

#database
df<-structure(list(Properties = c(1,2,3,4,5,6,7,8,9,10), Latitude = c(-23.2, -23.6, -23.9, -23.9, -23.6,  -23.5, -23.9, -23.9, -23.6, -23.9), 
Longitude = c(-49.6, -49.6, -49.6, -49.4, -49.3, -49.9, -49.3, -49.2, -49.6, -49.9)), class="data.frame",row.names = c(NA, -10L))

#clusters
d<-as.dist(distm(df[,2:1]))
fit.average<-hclust(d,method="average") 
clusters<-cutree(fit.average, 4) 
df$cluster<-clusters

#Map using leaflet

example=df
getColor <- function(example) {
  sapply(example$cluster, function(cluster) {
    if(cluster == 1) {
      "blue"
    } else if(cluster == 2) {
      "green"
    } else if(cluster == 3) {
      "orange"
    } else {
      "red"
    } })
}

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

m=leaflet(example) %>% addTiles() %>%
  addAwesomeMarkers(lat=~Latitude, lng = ~Longitude, icon=icons, label=~as.character(cluster))
m

enter image description here

Thank you very much!!

Insert addLegend

df1<-structure(list(Properties = c(1,2,3,4,5), Latitude = c(-23.8, -23.4, -23.2, -23.7,-23.8), 
Longitude = c(-49.9, -49.2, -49.3, -49.1,-49.9)), class="data.frame",row.names = c(NA, -5L))

m = leaflet(example) %>% addTiles() %>%
  addAwesomeMarkers(lat =  ~ Latitude,lng = ~ Longitude,icon = icons,label =  ~ as.character(cluster)) %>% 
addLegend( position = "topright", title="Cluster", colors = ai_colors[1:max(df$cluster)],labels = unique(df$cluster))%>%
addAwesomeMarkers(leaflet(df1) %>% addTiles(), lat=~df1$Latitude, lng = ~df1$Longitude)
m

Image as example:

enter image description here

Antonio
  • 1,091
  • 7
  • 24

1 Answers1

2

One good and simple way to assign colors to clusters is to simply index a vector of colors by a vector of clusters. In R colors can be specified as names ('white', 'red') or as numbers. And there is a built in function ?colors() that makes it easy to sample or index by another numeric vector:

> colors()[c(1,4,5,6,9)]
[1] "white"         "antiquewhite1" "antiquewhite2" "antiquewhite3" "aquamarine1" 

But leaflet::awesomeIcons only supports certain colors that look pretty good. You can get this list from ?awesomeIcons:

markerColor
Possible values are "red", "darkred", "lightred", "orange", "beige", "green", "darkgreen", "lightgreen", "blue", "darkblue", "lightblue", "purple", "darkpurple", "pink", "cadetblue", "white", "gray", "lightgray", "black"

So we can put these in a vector and index them with the cluster column:

ai_cols <- c("red", "darkred", "lightred", "orange", "beige", "green", "darkgreen", "lightgreen", "blue", "darkblue", "lightblue", "purple", "darkpurple", "pink", "cadetblue", "white", "gray", "lightgray", "black")
ai_cols[example$cluster]
[1] "red"      "red"      "darkred"  "darkred"  "lightred" "lightred" "orange"   "orange"   "orange"   "orange" 

This will work as long as the number of clusters is less than or equal to the number of colors allowed in awesomeIcons.


Full code:

library(leaflet)
library(geosphere)

#database
df <-
  structure(
    list(
      Properties = c(1, 2, 3, 4, 5, 6, 7, 8, 9, 10),
      Latitude = c(
        -23.2,
        -23.6,
        -23.9,
        -23.9,
        -23.6,
        -23.5,
        -23.9,
        -23.9,
        -23.6,
        -23.9
      ),
      Longitude = c(
        -49.6,
        -49.6,
        -49.6,
        -49.4,
        -49.3,
        -49.9,
        -49.3,
        -49.2,
        -49.6,
        -49.9
      )
    ),
    class = "data.frame",
    row.names = c(NA,-10L)
  )

#clusters
d <- as.dist(distm(df[, 2:1]))
fit.average <- hclust(d, method = "average")
clusters <- cutree(fit.average, 4)
df$cluster <- clusters

#Map using leaflet

example = df
ai_colors <-
  c(
    "red",
    "darkred",
    "lightred",
    "orange",
    "beige",
    "green",
    "darkgreen",
    "lightgreen",
    "blue",
    "darkblue",
    "lightblue",
    "purple",
    "darkpurple",
    "pink",
    "cadetblue",
    "white",
    "gray",
    "lightgray",
    "black"
  )

clust_colors <- ai_colors[example$cluster]

icons <- awesomeIcons(
  icon = 'ios-close',
  iconColor = 'black',
  library = 'ion',
  markerColor = clust_colors
)

m = leaflet(example) %>% addTiles() %>%
  addAwesomeMarkers(
    lat =  ~ Latitude,
    lng = ~ Longitude,
    icon = icons,
    label =  ~ as.character(cluster)
  )
m

Edit: add two sets of points in one legend

We can combine the points of the second dataset with the first, and plot them together. Then when we add legend, everything is going to be together.

We can add a cluster number 19 for the second set of points. This would correspond to the last color in the awesomeIcons color set. (You can set this to anything, but keep in mind the number of clusters vs. number of available colors.)

df1 <-
  structure(
    list(
      Properties = c(1, 2, 3, 4, 5),
      Latitude = c(-23.8,-23.4,-23.2,-23.7, -23.8),
      Longitude = c(-49.9,-49.2,-49.3,-49.1, -49.9)
    ),
    class = "data.frame",
    row.names = c(NA,-5L)
  )


df1$cluster <- 19
all_points <- rbind(example, df1)

Then plot as before:

clust_colors <- ai_colors[all_points$cluster]

icons <- awesomeIcons(
  icon = 'ios-close',
  iconColor = 'black',
  library = 'ion',
  markerColor = clust_colors
)

m = leaflet(all_points) %>% addTiles() %>%
  addAwesomeMarkers(
    lat =  ~ Latitude,
    lng = ~ Longitude,
    icon = icons,
    label =  ~ as.character(all_points$cluster)
  ) %>%
  addLegend(
    position = "topright",
    title = "Cluster",
    colors = ai_colors[unique(all_points$cluster)],
    labels = unique(all_points$cluster)
  ) 
m
teofil
  • 2,344
  • 1
  • 8
  • 17
  • Thank you very much Teofil. It helped me a lot. One more thing, if you can help me. I would like to insert a legend on the map referring to the clusters, so that I know which is cluster 1, cluster 2 and so on. – Antonio May 04 '20 at 21:22
  • Have a look at `?leaflet::addLegend`. Something like this maybe: `... %>% addLegend( position = "topright", colors = ai_colors[1:max(example$cluster)], labels = unique(example$cluster) )` – teofil May 05 '20 at 00:38
  • Wonderful, thanks Teofil. Just to check, do you think it is very difficult to solve the other question ?? https://stackoverflow.com/questions/61595335/find-the-shortest-path-between-points-on-a-map-made-by-the-leaflet-package/61597817#61597817 I tried to do some things, but without effectiveness. – Antonio May 05 '20 at 01:11
  • Teofil, I managed to insert the legend of my clusters, it was very good. However, I added one more database "df1" and merged the two maps into one. But I would like to add the legend for this second map (df1) that I created in the same legend as the first, could you help me with that? I entered the code above, I just need help with addLegend. Thanks! – Antonio May 06 '20 at 15:11
  • Have a look at my edit. An easy way to have two sets of points in one legend is to combine the points and plot them together. – teofil May 06 '20 at 22:55
  • Thanks for reply. I liked it. But in reality, this df1 database is not part of the cluster, even though they are from the same map and close together, they are distinct points of the cluster. I would just like to add the legend of the second database within the first, similar to the image I put in the attachment above, which presents different formats in the same legend. Sorry if I complicated I can ask a new question for you to answer if you want. – Antonio May 06 '20 at 23:58
  • If you want different legends, or different shapes on a single legend, then you probably need to plot your points with different shapes. In any case, you can add two separate legends with leaflet. Have a look here to get started: https://stackoverflow.com/questions/50641092/r-leaflet-map-change-legends-based-on-selected-layer-group. – teofil May 07 '20 at 00:39
  • Hello @teofil, any tip for this question: https://stackoverflow.com/questions/68854121/insert-color-into-google-maps-in-r – Antonio Aug 20 '21 at 00:01