0

I have the shiny app below in which I display df with ggplotly() barchart and and df2 with a datatable. The 2 dataframes have a column with same informations (dose). I would like to be able to click on a bar and automatically subset the df2 displayed in the table to the respective data. For example if I press D1 bar only the D1 data will be displayed in the table.

library(shiny)
library(ggplot2)
library(plotly)
library(DT)
ui <- fluidPage(
  plotlyOutput("plt"),
  DTOutput("dt")
)
server <- function(input, output) {
  df <- data.frame(dose=c("D0.5", "D1", "D2"),
                   len=c(4.2, 10, 29.5))
  output$plt<-renderPlotly({
    # Basic barplot
    p<-ggplot(data=df, aes(x=dose, y=len)) +
      geom_bar(stat="identity")
    ggplotly(p)
  })
  df2 <- data.frame(dose=c("D0.5", "D1", "D2"),
                   siz=c(2, 10, 2.5))
  output$dt<-renderDT(
    df2
  )
}
shinyApp(ui, server)

1 Answer 1

1

As long as your dataset is not to large, have a look at the crosstalk package here. It's designed for interaction between plots, maps and tables.

Automatically Subsetting

library(shiny)
library(ggplot2)
library(plotly)
library(DT)
library(crosstalk)

ui <- fluidPage(
  plotlyOutput("plt"),
  DT::dataTableOutput("dt")
)

server <- function(input, output) {
  df <- data.frame(dose=c("D0.5", "D1", "D2"),
                   len=c(4.2, 10, 29.5))
  df2 <- data.frame(dose=c("D0.5", "D1", "D2"),
                    siz=c(2, 10, 2.5))
  
  shared_df <- SharedData$new(df, key = ~dose, group = "group")
  shared_df2 <- SharedData$new(df2, key = ~dose, group = "group")
  
  output$plt<-renderPlotly({
    # Basic barplot
    p <- ggplot(data=shared_df, aes(x=dose, y=len)) +
      geom_bar(stat="identity")
    ggplotly(p)
  })
  
  output$dt<-DT::renderDataTable({
    shared_df2
    }, server = FALSE)
}
shinyApp(ui, server)

Manually Subsetting df2

library(shiny)
library(ggplot2)
library(plotly)
library(DT)
library(crosstalk)

ui <- fluidPage(
  plotlyOutput("plt"),
  DT::dataTableOutput("dt")
)

server <- function(input, output) {
  df <- data.frame(dose=c("D0.5", "D1", "D2"),
                   len=c(4.2, 10, 29.5),
                   stringsAsFactors = F) 
  df2 <- data.frame(dose=c("D0.5", "D1", "D2"),
                    siz=c(2, 10, 2.5),
                    stringsAsFactors = F)
  
  shared_df <- SharedData$new(df, key = ~dose, group = "group")

  output$plt<-renderPlotly({
    # Basic barplot
    p <- ggplot(data=shared_df, aes(x=dose, y=len)) +
      geom_bar(stat="identity")
    ggplotly(p)
  })
  
  dose_filter <- reactive({
         log <- shared_df$selection()
         if(!is.null(log)) {
           log <- shared_df$key()[log]
         } else {
           log <- shared_df$key()
         }
  })
  
   output$dt<- DT::renderDataTable({
    subset(df2, dose %in% dose_filter())
  }, server = FALSE)
  
}
shinyApp(ui, server)
Sign up to request clarification or add additional context in comments.

4 Comments

great answer indeed. could you look at this one for crosstalk? stackoverflow.com/questions/66508869/…
is possible to connect many charts to one table?
With regard to your later questions (4 datasets - 3 plots and 1 table) and your aim that only the table and not the plots should react, I think crosstalk in flexdashboard is not able to do that without shiny. You might need a reactive function to filter your table dataset like in the second example above. Than each of the 3 plot-datasets need to be converted into a sharedDataframe (each one with it's own group argument and the key might be the x-axis variable of the plot). And than you can filter your table-dataset with the three sharedDataframes in a reactive-function.
Thanks could you check whis does not work as expected? stackoverflow.com/questions/66537874/…

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.