-
Notifications
You must be signed in to change notification settings - Fork 1.9k
Brushing issue with facet_grid when scales="free",space="free" #1433
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
Comments
I have the same issue. now uncheck the checkbox the brushed region is shown at the first level where there is no data: require(shiny)
require(ggplot2)
mtcars$wt2 <- cut(mtcars$wt,4)
mtcars$mpg2 <- cut(mtcars$mpg,4)
ui <- basicPage(
plotOutput("plot1",
click = "plot_click",
dblclick = "plot_dblclick",
hover = "plot_hover",
brush = "plot_brush"
),
verbatimTextOutput("info"),
verbatimTextOutput("info2")
)
server <- function(input, output) {
output$plot1 <- renderPlot({
ggplot(mtcars, aes(wt2,mpg))+
geom_point()+
facet_grid(~mpg2,scales="free_x")
})
#
output$info <- renderText({
xy_str <- function(e) {
if(is.null(e)) return("NULL\n")
paste0("x=", round(e$x, 1), " y=", round(e$y, 1), "\n")
}
xy_range_str <- function(e) {
if(is.null(e)) return("NULL\n")
paste0("xmin=", round(e$xmin, 1), " xmax=", round(e$xmax, 1),
" ymin=", round(e$ymin, 1), " ymax=", round(e$ymax, 1))
}
paste0(
"click: ", xy_str(input$plot_click),
"dblclick: ", xy_str(input$plot_dblclick),
"hover: ", xy_str(input$plot_hover),
"brush: ", xy_range_str(input$plot_brush)
)
})
output$info2 <- renderPrint({
brushedPoints(mtcars, input$plot_brush)
})
}
shinyApp(ui, server)
Using |
@smouksassi I don't see a checkbox in your example. The root cause is the way that ggplot converts the categorical/discrete x scales (in both of your examples) to numeric values. We're able to get the numeric x value, where each "tick" on the x axis is 1, 2, 3. etc., but then we have the problem of translating those values back to the categorical values. I'm not 100% sure offhand, but I don't think that the ggplot object has a straightforward way to get the mapping between numeric x value and categorical value for individual panels. If this is very important, your best course of action for the time being may be to do the inverse mapping manually. Since you know which horizontal faceting value you have ( |
Hi Winston, require(shiny)
require(ggplot2)
mtcars$wt2 <- cut(mtcars$wt,4)
mtcars$mpg2 <- cut(mtcars$mpg,4)
ui <- basicPage(
plotOutput("plot1",
click = "plot_click",
dblclick = "plot_dblclick",
hover = "plot_hover",
brush = "plot_brush"
),
checkboxInput("freex","Free x Scales",value=TRUE),
verbatimTextOutput("info"),
verbatimTextOutput("info2")
)
server <- function(input, output) {
output$plot1 <- renderPlot({
p<- ggplot(mtcars, aes(wt2,mpg))+
geom_point()+
facet_grid(~mpg2)
if(input$freex)
p<- p+ facet_grid(~mpg2,scales="free_x")
p
})
#
output$info <- renderText({
xy_str <- function(e) {
if(is.null(e)) return("NULL\n")
paste0("x=", round(e$x, 1), " y=", round(e$y, 1), "\n")
}
xy_range_str <- function(e) {
if(is.null(e)) return("NULL\n")
paste0("xmin=", round(e$xmin, 1), " xmax=", round(e$xmax, 1),
" ymin=", round(e$ymin, 1), " ymax=", round(e$ymax, 1))
}
paste0(
"click: ", xy_str(input$plot_click),
"dblclick: ", xy_str(input$plot_dblclick),
"hover: ", xy_str(input$plot_hover),
"brush: ", xy_range_str(input$plot_brush)
)
})
output$info2 <- renderPrint({
brushedPoints(mtcars, input$plot_brush)
})
}
shinyApp(ui, server) |
I ran into this problem today and implemented the solution Winston (@wch) outlined above. (At least I think that's what he had in mind.) Perhaps it's useful to others, so here is my workaround for the example provided by Samer (@smouksassi) above. (I just added a few lines within the call to I used dplyr's require(shiny)
require(ggplot2)
require(dplyr)
mtcars$wt2 <- cut(mtcars$wt,4)
mtcars$mpg2 <- cut(mtcars$mpg,4)
ui <- basicPage(
plotOutput("plot1",
click = "plot_click",
dblclick = "plot_dblclick",
hover = "plot_hover",
brush = "plot_brush"
),
verbatimTextOutput("info"),
verbatimTextOutput("info2")
)
server <- function(input, output) {
output$plot1 <- renderPlot({
ggplot(mtcars, aes(wt2,mpg))+
geom_jitter(width = 0.1) + # a few plots overlap, so let's jitter a bit
facet_grid(~mpg2,scales="free_x")
})
output$info <- renderText({
xy_str <- function(e) {
if(is.null(e)) return("NULL\n")
paste0("x=", round(e$x, 1), " y=", round(e$y, 1), "\n")
}
xy_range_str <- function(e) {
if(is.null(e)) return("NULL\n")
paste0("xmin=", round(e$xmin, 1), " xmax=", round(e$xmax, 1),
" ymin=", round(e$ymin, 1), " ymax=", round(e$ymax, 1))
}
paste0(
"click: ", xy_str(input$plot_click),
"dblclick: ", xy_str(input$plot_dblclick),
"hover: ", xy_str(input$plot_hover),
"brush: ", xy_range_str(input$plot_brush)
)
})
output$info2 <- renderPrint({
req(input$plot_brush) # only execute when points are brushed
##--- identify brushed subset of the mtcars data.frame without brushedPoints
# I use shorter variable names for better readability
facet.var <- input$plot_brush$mapping$panelvar1 # column used for faceting
x.axis.var <- input$plot_brush$mapping$x # column used for x-axis
y.axis.var <- input$plot_brush$mapping$y # column used fo y-axis
facet.value <- input$plot_brush$panelvar1 # level of the brushed facet
# First, subset the data.frame to those rows that match the brushed facet level
mtcars <- dplyr::filter_(
mtcars,
sprintf("%s == '%s'", facet.var, facet.value))
# Next, drop levels not used in the current facet
mtcars <- droplevels(mtcars)
# Finally, within this facet, identify points within the brushed ranges
mtcars %>%
dplyr::filter(
# interpret the factor levels as integers, to match how ggplot2
# places them on the axes. The 'droplevels' call above ensures that
# only levels that are present in the current facet are matched
as.integer(mtcars[[x.axis.var]]) < input$plot_brush$xmax,
as.integer(mtcars[[x.axis.var]]) > input$plot_brush$xmin,
mtcars[[y.axis.var]] < input$plot_brush$ymax,
mtcars[[y.axis.var]] > input$plot_brush$ymin
)
})
}
shinyApp(ui, server) |
It's not obvious to me how we could make this "just work" from Shiny, since the mapping operation outlined by @wch seems to require information about the ggplot object that we can't infer automatically. I'll consult with the team and either outline a strategy to fix or close the issue, since workarounds have been provided. |
this still does not work if we have the free scales with @tomsing1 code |
…posed in brushedPoints(), closes #1433
thank you finally this is solved one small thing is that we get this warning to console : Input to asJSON(keep_vec_names=TRUE) is a named vector. In a future version of jsonlite, this option will not be supported, and named vectors will be translated into arrays instead of objects. If you want JSON object output, please use a named list instead. See ?toJSON. |
@smouksassi if you could a produce a MRE that would be much appreciated! |
might be related to jeroen/jsonlite#76 and I found this unanswered question |
Hi, |
@kevinrue that looks like a different issue, could you please file a new issue with a more precise description of the problem? |
Will do, thanks for the reply! |
Uh oh!
There was an error while loading. Please reload this page.
In R Shiny, when we brush points in ggplot, there is something wrong with the facet_grid function when scales="free",space="free".
For example, the following code works fine.
But when we set scales="free",space="free", the selection goes wrong.
How can we solve this issue?
http://stackoverflow.com/questions/40150136/r-shiny-brush-facet-grid-with-scales-free-space-free
The text was updated successfully, but these errors were encountered: