Home > Mobile >  Variable Alpha in ggplot map based on shiny input
Variable Alpha in ggplot map based on shiny input

Time:08-24

Say I have a data set that looks something like this:

Number Name lat long
1 A 45 100
2 B 46 100
3 C 47 100
... ... ... ...
2000 AAA 48 100

I've built a shiny app that displays them all on a map based on a slider input:

#slider input: 
sliderInput("data", 
                        "Number",
                        min = 1,
                        max = max(data$number),
                        value = c(1,100))
#reactive to plot from
plot_data <- reactive({ data %>% filter(number <= max(input$data), number >= min(input$data))})

#map
output$distPlot <- renderPlotly({
        mymap <- ggplot(states)   geom_sf()   geom_point(data = plot_data(), aes(x = 
        long, y = lat, color = number, text = name), alpha = a)   
        scale_colour_viridis_c("Number", option = 'mako', direction = 1)
        ggplotly(mymap, tooltip = c("number", "text"))

This works great when displaying the initial values of numbers 1-100. However, if I move the slider to plot all the points 1-2000, things get a bit cluttered. If I set alpha = 0.1 or 0.2, it works fine. I don't want to set this as a fixed value though, because alpha = 1 looks better when fewer points are plotted.

So, is there a way to vary alpha based on the number of points being plotted? This way, alpha can be close to 1 when there are fewer points selected with the slider, and closer to 0 when most of the points are selected. I think ideally, for X points plotted,

$$alpha = -\frac{0.9}{1999}(x-1) 1,$$

should work fine.

I've tried typing this kind of formula directly into the aes(), replacing x with count(input$data) or (max(input$data) - min(input$data)). This hasn't worked. I've also tried creating another reactive for x using the same count, max/min functions. This also hasn't worked. Why not and how can I do this instead? Thank you.

CodePudding user response:

For your needs, I don't think you need anything fancy or set dynamically within aesthetics. I think the most straight-forward is to do the determination yourself and set it as a static-alpha for that plot. For this, if you divide 200 by the number of rows in the frame and clamp it so it does not exceed 1, then it'll give you an alpha=1 at 100 rows and alpha=0.1 with 2000 rows.

pmin(1, 200 / c(10, 50, 100, 500, 1000, 2000))
# [1] 1.0 1.0 1.0 0.4 0.2 0.1

That shows that frames with 10, 50, 100, ... rows will get an alpha value of 1, 1, etc. I use pmin here to keep it from going above 1, but that's because I'm demonstrating against multiple numbers; otherwise min will work fine.

For instance,

output$distPlot <- renderPlotly({
  req(nrow(plot_data()) > 0)
  this_alpha <- min(1, 200 / nrow(plot_data()))
  mymap <- ggplot(states)  
    geom_sf()  
    geom_point(data = plot_data(), aes(x = long, y = lat, color = number, text = name),
               alpha = this_alpha)  
    scale_colour_viridis_c("Number", option = 'mako', direction = 1)
  ggplotly(mymap, tooltip = c("number", "text"))
})
  • Related