I am currently developing a reactive map on Shiny. This map is basically a US map where a selectors enables the user to display different quality variables. The data frame used (called data
)looks as follows (data here is randomised) :
head(data)
state year color leaf mike_value strength length color_leaf_grade staple
1 Alabama 2020 41 1 40.24 300.12 37.00 31-4 34
2 Arkansas 2020 31 1 45.57 300.12 37.80 31-4 34
3 Arizona 2020 11 2 45.51 300.12 37.11 11-2 34
4 California 2020 11 2 45.94 300.12 39.40 others 34
5 Florida 2020 21 3 45.83 300.12 37.18 31-1 37
6 Georgia 2020 41 3 45.06 300.12 36.58 others 37
I am encountering an issue with the color_leaf_grade
variable. Indeed, unlike the other variables such as color
or leaf
which are numeric, color_leaf_grade
is a factor. I would like to color the map according to the different factor levels (in total 4 different levels). However, when I do so, I obtain some weird things. As can be seen on the screenshot below, it colours the different states according to the level to which they belong (which is what I want) but instead of displaying the names of the levels in both the legend and the pop-up that appears when hovering the map with the mouse, it displays values 1, 2, 3, 4. I already tried to assign new names to the factor levels, yet it doesn't work.
Here is what I have in the ui
part of my Shiny app for my map widget:
tabItem(tabName = "dashboard_map",
fluidRow(
box(selectInput("variable_selected",
label = "Select variable",
choices = c(
"Color" = "color",
"Leaf" = "leaf",
"Mike" = "mike_value",
"Strength" = "strength",
"Length" = "length",
"Color leaf grade" = "color_leaf_grade",
"Staple" ="staple"
)),
width = 9)
),
fluidRow(
box(leafletOutput(outputId = "map"), width = 9),
box(selectInput("myear_selected",
label = "Marketing year:",
choices=c(year_range),
selected = year_range[length(year_range)]),
width = 3)),
Here is what I have in the server
part of my Shiny app for my map widget:
# MAP
output$map <- renderLeaflet({
# Add data to map
datafiltered <- data[which(data$year == input$myear_selected),]
orderstates <- match(map@data$STATE_NAME, datafiltered$state)
map@data <- datafiltered[orderstates,]
# Create variableplot
# ADD this to create variableplot
map$variableplot <- as.numeric(map@data[, input$variable_selected])
# Create leaflet
pal <- colorBin("YlOrRd",
domain = map$variableplot,
bins = 5)
labels <- sprintf("%s: %g",map$state, map$variableplot) %>%
lapply(htmltools::HTML)
l <-
leaflet(map, options = leafletOptions(zoomSnap = 0.25, zoomDelta = 0.25,zoomControl = FALSE)) %>%
addTiles() %>%
setView(lng = -98,
lat = 36,
zoom = 3.75) %>%
addPolygons(
fillColor = ~ pal(variableplot),
color = "white",
dashArray = "3",
fillOpacity = 0.7,
label = labels
) %>%
leaflet::addLegend(
"bottomright",
pal = pal,
values = ~ variableplot,
opacity = 0.7,
title = NULL
)
})
Does anyone here have an idea about whether it is possible when building such a reactive map to account for other numeric and categorical types of value?
Thank you very much in advance for your help and happy new year.
CodePudding user response:
In sprintf("%s: %g",map$state, map$variableplot)
, the values of the factor variable map$variableplot
are used (which are just numbers), but you want the levels
. (Factor variables are just numbers, where each number is assigned a level. You can check it with str(map$variableplot)
.) Try the below that extracts the levels when a factor is present:
variableplot_clean <- ifelse(is.factor(map$variableplot),
levels(map$variableplot), map$variableplot)
labels <- sprintf("%s: %s",map$state, variableplot_clean) %>%
lapply(htmltools::HTML)
CodePudding user response:
Since color_leaf_grade
is a factor variable, you could use the colorFactor function to generate the palette. You can specify the color for each level in the factor set, like this:
pal <- colorFactor(palette = c("red","yellow","orange","green"),
levels = c("31-1","11-2","others","factor4..."))
And then your addPolygons would look like this:
addPolygons(
fillColor = ~pal(color_leaf_grade),
color = "white",
dashArray = "3",
fillOpacity = 0.7,
label = labels
)