0

I'm trying to color in a map with the leaflet package using data that looks as such:

+--------+---------+-------+
| region | terrain | sales |
+--------+---------+-------+
|      1 | 1A      |   253 |
|      1 | 1B      |   280 |
|      1 | 1C      |   360 |
|      1 | 1D      |   350 |
|      1 | 1E      |   335 |
|      1 | 1F      |   275 |
|      2 | 2A      |   200 |
|      2 | 2B      |   300 |
|      2 | 2C      |   400 |
|      2 | 2D      |   250 |
|      2 | 2E      |   350 |
+--------+---------+-------+

While I know how to create a color palette based off one variable, I would like to create one based on each variables "parent"

So let's say I want 1 = "Reds" and 2 = "Blues" but within those two "parent" colors, I then want all of the terrains within those regions to be shaded in accordance to sales?

2 Answers2

1

This doesn't explicitly use leaflet but uses RColorBrewer (which leaflet imports)

This function will split the dataframe by the first column given and give each value in the second a colour from each of the Pals in turn.

At the end I've assigned this to a column, but you may want to use it differently.

library(RColorBrewer)
library(dplyr)
createCustomPalette <- function(df, parentCol = "region",subCol = "terrain",
                                Pals = c("Blues", "Reds", "Greens", "Greys", "Oranges", "Purples"),
                                returnDF = FALSE){
  Parents <- as.numeric(unique(df[[parentCol]]))

  ParCols <- lapply(seq_along(Parents), function(x) 
    RColorBrewer::brewer.pal(length(unique(df[df[parentCol]==Parents[x],subCol])), Pals[x]))


  Cols <- unlist(ParCols) 

  Colsdf <- data.frame(Col = Cols, sub = unlist(lapply(Parents, function(x) unique(df[df[[parentCol]]==x,][[subCol]]))),
                       stringsAsFactors = F)

  outdf <- dplyr::right_join(Colsdf,df, by = c("sub"=subCol))

  # outdf <- merge(df, Colsdf, by.x = subCol, by.y = "sub", all.x = T, sort = FALSE )

  if(returnDF){
    return(outdf) 
  }else{
    return(outdf$Col)
  }
}
mydf$Cols <- createCustomPalette(mydf)
scales::show_col(mydf$Cols)

I tried to avoid using dplyr because I didn't want to add new libraries but merging and maintaining row order (which is important if you are just getting colours) is a pain in base R. If you don't want to use dplyr you'll just have to add rownumbers and merge and then sort.

Sarah
  • 3,022
  • 1
  • 19
  • 40
  • I realised that my previous one would have given incorrect values if there were duplicates so I have updated. – Sarah Sep 16 '19 at 00:45
1

You can use library(colourvalues) to generate specific colours for vectors / columns of data

Setting up data

## using a known / reproducible data object
df <- mapdeck::capitals

## making a 'region' column to represent your data
df$region <- ifelse( tolower( substr(df$country,1,1) ) %in% letters[1:13], 1, 2 )

## a random 'sales' column
df$sales <- rnorm(n = nrow(df) )

Colouring

library(colourvalues)

## order the data first so we can simply `<- c()` the result
df <- df[with(df, order(region)), ]


region1 <- colour_values( x = df[ df$region == 1, "sales"], palette = "reds" )
region2 <- colour_values( x = df[ df$region == 2, "sales"], palette = "blues")

df$colours <- c(region1, region2)

Plotting

library(leaflet)

leaflet() %>%
  addTiles() %>%
  addCircles(
    data = df
    , color = df$colours
  )

enter image description here

SymbolixAU
  • 25,502
  • 4
  • 67
  • 139
  • If your data.frame isn't ordered by region then this won't give the correct colours for the correct regions – Sarah Sep 16 '19 at 07:22