Bring Drag & Drop to Dash with Dashboard Engine. 💫 Learn how at our next webinar!

Modifying multiple attributes to update x axis, y axis and legend in a grouped box plot

Hi,

I have successfully created separate grouped box plots, each for 1 group of data and am now trying to combine all these with a dropdown and legend. To give a reproducible example that is similar to my own data, I will split the ggplot2::diamond data into 2 groups and combine them. My data have more groups than 2. I am hoping to select a subset of data, probably via a dropdown, and then the plot will update its x axis, y axis and legend (specified by the color= argument in the plot_ly()). I have tried to modify the code from this post Plotly R : Modify several attributes from a single restyle button but I haven’t been able to make my plot work.

#----------------------------------------------
# Use the diamonds dataset for making box plots
#----------------------------------------------
str(ggplot2::diamonds) # dim(diamonds) 53940 10

# Split data into 2 groups
diamonds.1 <- ggplot2::diamonds %>% 
  dplyr::filter(clarity %in% c("SI2","SI1","VS1","VS2")) %>%
  dplyr::mutate(ID="group 1") # dim(diamonds.1) 42688 11 

diamonds.2 <- ggplot2::diamonds %>% 
  dplyr::filter(clarity %in% c("VVS2","VVS1","I1","IF")) %>%
  dplyr::mutate(ID="group 2") # dim(diamonds.2) 11252 11 

#-------------------------------------------------
# Make 1 grouped box plot per diamonds.1 (working)
#-------------------------------------------------
fig1 <- plot_ly(data = diamonds.1, x = ~cut, y = ~price, color = ~clarity, type = "box") %>%
  layout(boxmode="group")

#-------------------------------------------------
# Make 1 grouped box plot per diamonds.2 (working)
#-------------------------------------------------
fig2 <- plot_ly(data = diamonds.2, x = ~cut, y = ~price, color = ~clarity, type = "box") %>%
  layout(boxmode="group")

#-----------------------------------------------------------------------------------------------
# Make grouped box plots per diamonds.1 and diamonds.2 with 1 dropdown and legends (not working)
#-----------------------------------------------------------------------------------------------
diamonds <- dplyr::bind_rows(diamonds.1,diamonds.2)

x1 <- diamonds[ which(diamonds$ID=='group 1'),"cut"]
x2 <- diamonds[ which(diamonds$ID=='group 2'),"cut"]

y1 <- diamonds[ which(diamonds$ID=='group 1'),"price"]
y2 <- diamonds[ which(diamonds$ID=='group 2'),"price"]

color1 <- diamonds[ which(diamonds$ID=='group 1'),"clarity"]
color2 <- diamonds[ which(diamonds$ID=='group 2'),"clarity"]

fig <- plotly::plot_ly( diamonds, x = ~cut, y = ~price, color = ~clarity, type = "box") %>%
  plotly::layout(boxmode="group"
                 ,title = "Drop down menus - Styling"
                 ,xaxis = list(title= " Diamond Cut")
                 ,yaxis = list(title = "Diamond Price")
                 ,updatemenus = list(
                   list(
                     y = 0.7,
                     buttons = list(
                       # Modify attributes for option 1 in the dropdown list
                       list(method = "update" # "restyle": modify data or data attributes, "update": modify data and layout attributes
                            ,args= list(list(x=list(x1), y=list(y1), color=list(color1)
                                             )
                                        )
                            ,label = "Group 1")
                       # Modify attributes for option 2 in the dropdown list
                       ,list(method = "update"
                             ,args= list(list(x=list(x2), y= list(y2), color=list(color2))
                                         )
                             ,label = "Group 2")
                     )
                   )
                 )
  )
fig

I believe the problem is in the args= argument, which attribute names and values are specified in a list(). I have been confused by the list of list of list… In R, there is no dict(). So one would always change the dict() in Python to list() in R?

Hi, sorry for the late answer. I hope you either found a solution, or a solution is still usefull for you.

Your problem here is the shape of your data: x1, x2, y1, y2, color1 and color2 are not straight list of the data you want to plot.
They are frames, each of them containing a single column, which is the data you want to plot.

Try to print(x1) you’ll see :slight_smile: .

So, you need to correct like that:

##----------------------------------------------
## Use the diamonds dataset for making box plots
##----------------------------------------------
suppressMessages(library(plotly))
suppressMessages(library(dplyr))

str(ggplot2::diamonds) # dim(diamonds) 53940 10

# Split data into 2 groups
diamonds.1 <- ggplot2::diamonds %>% 
  dplyr::filter(clarity %in% c("SI2","SI1","VS1","VS2")) %>%
  dplyr::mutate(ID="group 1") # dim(diamonds.1) 42688 11 

diamonds.2 <- ggplot2::diamonds %>% 
  dplyr::filter(clarity %in% c("VVS2","VVS1","I1","IF")) %>%
  dplyr::mutate(ID="group 2") # dim(diamonds.2) 11252 11 

#-----------------------------------------------------------------------------------------------
# Make grouped box plots per diamonds.1 and diamonds.2 with 1 dropdown and legends (working ?)
#-----------------------------------------------------------------------------------------------
diamonds <- dplyr::bind_rows(diamonds.1,diamonds.2)

x1 <- diamonds[ which(diamonds$ID=='group 1'),"cut"]
x2 <- diamonds[ which(diamonds$ID=='group 2'),"cut"]
y1 <- diamonds[ which(diamonds$ID=='group 1'),"price"]
y2 <- diamonds[ which(diamonds$ID=='group 2'),"price"]

color1 <- diamonds[ which(diamonds$ID=='group 1'),"clarity"]
color2 <- diamonds[ which(diamonds$ID=='group 2'),"clarity"]

fig <- plotly::plot_ly( diamonds, x = ~cut, y = ~price, color = ~clarity, type = "box") %>%
  plotly::layout(title = "Drop down menus - Styling"
                 ,xaxis = list(title= " Diamond Cut")
                 ,yaxis = list(title = "Diamond Price")
                 ,updatemenus = list(
                   list(
                     y = 0.7,
                     buttons = list(
                       # Modify attributes for option 1 in the dropdown list
                       list(method = "update" # "restyle": modify data or data attributes, "update": modify data and layout attributes
                           ,args= list(list(x=list(x1$cut), y=list(y1$price), color=list(color1$clarity)))
                           ,label = "Group 1")
                       # Modify attributes for option 2 in the dropdown list
                       ,list(method = "update"
                             ,args= list(list(x=list(x2$cut), y= list(y2$price), color=list(color2$clarity)))
                             ,label = "Group 2")
                     )
                   )
                  )
                 )

htmlwidgets::saveWidget(as_widget(fig), "luenMWE.html")