-
Notifications
You must be signed in to change notification settings - Fork 628
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Parallel coordinates plot not triggering events with Shiny #1321
Comments
Wow, nice investigation, and thanks for the thorough report! You're right about library(plotly)
library(shiny)
ui <- fluidPage(
plotlyOutput("parcoords"),
tableOutput("data")
)
server <- function(input, output, session) {
iris_numeric <- dplyr::select_if(iris, is.numeric)
output$parcoords <- renderPlotly({
dims <- Map(function(x, y) {
list(values = x, range = range(x), label = y)
}, iris_numeric, names(iris_numeric), USE.NAMES = FALSE)
plot_ly(type = 'parcoords', dimensions = dims, source = "pcoords")
})
# maintain a collection of selection ranges
# since each parcoord dimension is allowed to have multiple
# selected ranges, this reactive values data structure is
# allowed
# list(
# var1 = list(c(min1, max1), c(min2, max2), ...),
# var2 = list(c(min1, max1)),
# ...
# )
ranges <- reactiveValues()
observeEvent(event_data("plotly_restyle", source = "pcoords"), {
d <- event_data("plotly_restyle", source = "pcoords")
# what is the relevant dimension (i.e. variable)?
dimension <- as.numeric(stringr::str_extract(names(d[[1]]), "[0-9]+"))
# careful of the indexing in JS (0) versus R (1)!
dimension_name <- names(iris_numeric)[[dimension + 1]]
# a given dimension can have multiple selected ranges
# these will come in as 3D arrays, but a list of vectors
# is nicer to work with
info <- d[[1]][[1]]
ranges[[dimension_name]] <- if (length(dim(info)) == 3) {
lapply(seq_len(dim(info)[2]), function(i) info[,i,])
} else {
list(as.numeric(info))
}
})
# filter the dataset down to the rows that match the selection ranges
iris_selected <- reactive({
keep <- TRUE
for (i in names(ranges)) {
range_ <- ranges[[i]]
keep_var <- FALSE
for (j in seq_along(range_)) {
rng <- range_[[j]]
keep_var <- keep_var | dplyr::between(iris[[i]], min(rng), max(rng))
}
keep <- keep & keep_var
}
iris[keep, ]
})
output$data <- renderTable({
iris_selected()
})
}
shinyApp(ui, server) It would be nice to try and emit essentially the result of |
The above example is no longer working using plotly 4.10.0 Edit: I found a working version here. |
Hi,
There is a bug regarding the events sent by parallel coordinates plot in
shiny
.As far as I understand it, parallel coordinates are really different from usual
plotly
plots, as their axis, labels etc. do not work the same way as the others.The events are also affected, as they aren't emmited the same way as in other plots.
Here's an adapted version of the example given in Shiny Gallery.
Created on 2018-08-10 by the reprex package (v0.2.0).
As you can see when running this, whatever you do, no event is ever triggered (the 4 verbatim outputs remain with their default text).
This is because in parallel coordinates plots, none of
plotly_hover
,plotly_click
,plotly_selected
orplotly_relayout
are ever called.What's called, when brushing a selection, is the js
plotly_restyle
event.But this event contains not many significant thing, that is, only the last brushed selection, thus, not enabling to have a clear vision of what's selected.
Here's a demo app, using a custom binding with
htmlwidgets::onRender()
, showing the content of the event :Created on 2018-08-10 by the reprex package (v0.2.0).
As you can see, only the last selected dimension is shown, resulting in this json object:
Stringified, this results in this R string : ``` r
"[{"dimensions[2].constraintrange":[[0.08125,0.6906249999999999]]},[0]]"
I should note that I stringify this content instead of returning the js object directly because
jsonlite
conversions loose many informations about the object here. So, I have to do a custom R handling of this string, resulting in this demo app :Created on 2018-08-10 by the reprex package (v0.2.0).
Of course, this solution isn't optimal, because :
plotly_restyle
seems to be meaning different things among plotly plots, and thus, using such a code wouldn't be generic among plots for this R package.Yet, eventhough I currently don't have time to work on a PR (I just discovered plotly, and can't spend many time trying to understand the bindings with R right now), it would be fantastic if you could take this issue into consideration, and maybe use my "findings" (related to how events work with parallel coordinates) to fix this troublesome issue.
The text was updated successfully, but these errors were encountered: