rplotlyflexdashboardcrosstalk

How to conditionally set plotly axis range for a shared data set


I've built an R flexdashboard and am using an htmlwidget, crosstalk, to filter my dashboard's plotly charts.

My current issue is that data labels for a horizontal bar chart are being cut off. I'm trying to remedy this by adjusting the x-axis max. More specifically, I'm trying to tailor the x-axis max to the values of each filtered group, so that the chart produces an appropriate axis range for all groups.

I'm currently trying to do this in plotly with layout(xaxis = list(range = c(~xaxis_max[1])). However, this indexes the first value in the entire shared data set, rather than the first value in the filtered shared data set.

Any thoughts on how to adjust so that each group's chart has a group-specific axis maximum?

Full reprex below (chart displays as intended for team 1, axis not adjusting not team 2):

---
title: "Donut Dashboard"
output: 
  flexdashboard::flex_dashboard
---

```{r setsup, echo=FALSE} 
library(flexdashboard) 
library(plotly) 
library(tidyverse)
library(crosstalk)
``` 

my_tibble <- tibble(donuts_eaten = c(7436, 12761, 13153, 12707, 183, 377, 368, 381),
                    week = c(1,2,3,4,1,2,3,4),
                    donut_type = c("glazed", "chocolate", "cake", "sprinkle", 
                                  "glazed", "chocolate", "cake", "sprinkle"),
                    group = c("team 1", "team 1", "team 1", "team 1", 
                               "team 2", "team 2", "team 2", "team 2"))

#Create group-specific variable for x-axis max
my_tibble <- my_tibble %>% 
  group_by(group) %>% 
  mutate(xaxis_max = 1.5*max(donuts_eaten)) %>% 
  ungroup()

    my_tibble_shared <- SharedData$new(my_tibble, ~group)
    
    ```
    
    Column {data-width=650}
    -----------------------------------------------------------------------
    
    <!-- Create filter for plotly chart -->
    ### Filter
    
    ```{r}
    filter_select(
      id = "group",
      label = "Filter group:",
      sharedData = my_tibble_shared,
      group = ~group,
      multiple = F
    )
    ```
    
    ```{js}
    $(document).ready(function() {
        document.getElementById("group").getElementsByClassName("selectized")[0].selectize.setValue("team 1", false);
    });
    
    ```
    
    Column {data-width=350}
    -----------------------------------------------------------------------
    
    ### Donuts Eaten
    
    ```{r}
    #Create function to make horizontal bar chart for donuts eaten
    plot_ly(data = my_tibble_shared, hoverinfo = "none") %>% 
        
    #adjust x-axis max to show data labels
    layout(
      xaxis = list(range = c(0, ~xaxis_max[1])),
      showlegend = F) %>% 
    
    #plot donuts eaten by donut type 
    add_trace(
      x = ~donuts_eaten,
      y = ~donut_type,
      type = "bar") %>%  
    
    #place text labels on chart 
    add_text(
      x = ~donuts_eaten,
      y = ~donut_type,
      text = ~donuts_eaten,
      textposition = "right",
      textfont = list(color = "black"),
      showlegend = F,
      texttemplate = paste('<b> %{text:,.1d} </b>')) 
    ```

Solution

  • Perhaps a better solution exists, but I did find a workaround to this issue.

    I charted my x-axis max variable so that the x-axis would account for this as a data point. I then adjusted my y-axis so that the bar containing my desired x-axis max was not displayed on the chart.

    This is helpful if someone has a non-shiny flexdashboard containing plotly figures linked to a crosstalk filter. This solution allows the data labels to be fully displayed on all filtered charts, while maintaining a suitable x-axis range for each filtered level.

    I added this to my code above without changing anything else:

    #plot bar with xaxis max to adjust xaxis range 
    add_trace(
      x = ~xaxis_max,
      y = "z_xaxis_max", 
      type = "bar",
      transforms = list(
        list(
          type = "aggregate",
          groups = ~group,
          aggregations = list(
            list(
              target = "x", func = "max", enabled = T))))) %>%   
      
    #adjust x-axis max to show data labels
    layout(
      showlegend = F, 
      yaxis = list(title = none, range = c(-0.5,3.5))) %>%