Home > Software design >  Shiny: Clickable table to filter another table?
Shiny: Clickable table to filter another table?

Time:10-03

I have some data in a table format which looks like:

  capRates 1100000 1050000 1000000 950000 900000
1    0.088  0.0812  0.0928  0.1052 0.1185 0.1327
2    0.084  0.0892  0.1009  0.1134 0.1267 0.1409
3    0.080  0.0977  0.1095  0.1220 0.1354 0.1497
4    0.076  0.1068  0.1187  0.1313 0.1447 0.1591
5    0.072  0.1166  0.1285  0.1412 0.1547 0.1692

The second table looks like:

# A tibble: 6 × 25
  11000…¹ 11000…² 11000…³ 11000…⁴ 11000…⁵ 10500…⁶ 10500…⁷ 10500…⁸ 10500…⁹ 10500…˟ 10000…˟ 10000…˟ 10000…˟ 10000…˟ 10000…˟ 95000…˟ 95000…˟ 95000…˟ 95000…˟ 95000…˟ 90000…˟ 90000…˟
    <dbl>   <dbl>   <dbl>   <dbl>   <dbl>   <dbl>   <dbl>   <dbl>   <dbl>   <dbl>   <dbl>   <dbl>   <dbl>   <dbl>   <dbl>   <dbl>   <dbl>   <dbl>   <dbl>   <dbl>   <dbl>   <dbl>
1 -1.1 e6 -1.1 e6 -1.1 e6 -1.1 e6 -1.1 e6 -1.05e6 -1.05e6 -1.05e6 -1.05e6 -1.05e6 -1   e6 -1   e6 -1   e6 -1   e6 -1   e6 -9.5 e5 -9.5 e5 -9.5 e5 -9.5 e5 -9.5 e5 -9   e5 -9   e5
2  8   e4  8   e4  8   e4  8   e4  8   e4  8   e4  8   e4  8   e4  8   e4  8   e4  8   e4  8   e4  8   e4  8   e4  8   e4  8   e4  8   e4  8   e4  8   e4  8   e4  8   e4  8   e4
3  8.34e4  8.34e4  8.34e4  8.34e4  8.34e4  8.34e4  8.34e4  8.34e4  8.34e4  8.34e4  8.34e4  8.34e4  8.34e4  8.34e4  8.34e4  8.34e4  8.34e4  8.34e4  8.34e4  8.34e4  8.34e4  8.34e4
4  8.69e4  8.69e4  8.69e4  8.69e4  8.69e4  8.69e4  8.69e4  8.69e4  8.69e4  8.69e4  8.69e4  8.69e4  8.69e4  8.69e4  8.69e4  8.69e4  8.69e4  8.69e4  8.69e4  8.69e4  8.69e4  8.69e4
5  9.06e4  9.06e4  9.06e4  9.06e4  9.06e4  9.06e4  9.06e4  9.06e4  9.06e4  9.06e4  9.06e4  9.06e4  9.06e4  9.06e4  9.06e4  9.06e4  9.06e4  9.06e4  9.06e4  9.06e4  9.06e4  9.06e4
6  1.21e6  1.26e6  1.32e6  1.39e6  1.46e6  1.21e6  1.26e6  1.32e6  1.39e6  1.46e6  1.21e6  1.26e6  1.32e6  1.39e6  1.46e6  1.21e6  1.26e6  1.32e6  1.39e6  1.46e6  1.21e6  1.26e6
# … with 3 more variables: `900000-0.08` <dbl>, `900000-0.076` <dbl>, `900000-0.072` <dbl>, and abbreviated variable names ¹​`1100000-0.088`, ²​`1100000-0.084`, ³​`1100000-0.08`,
#   ⁴​`1100000-0.076`, ⁵​`1100000-0.072`, ⁶​`1050000-0.088`, ⁷​`1050000-0.084`, ⁸​`1050000-0.08`, ⁹​`1050000-0.076`, ˟​`1050000-0.072`, ˟​`1000000-0.088`, ˟​`1000000-0.084`,
#   ˟​`1000000-0.08`, ˟​`1000000-0.076`, ˟​`1000000-0.072`, ˟​`950000-0.088`, ˟​`950000-0.084`, ˟​`950000-0.08`, ˟​`950000-0.076`, ˟​`950000-0.072`, ˟​`900000-0.088`, ˟​`900000-0.084`

The column names of the second table correspond to a paste of the colnames and rownames of the first table. i.e. the column: 1100000-0.088 corresponds to the first row and first column in table1 with a value of 0.0812. Another example is, 950000-0.076 which corresponds to row 4 column 5 in table1 - or under the column 950000 and row 0.076.

I want to create a "filter" or "select" based on a square in table 1. That is, if the user (in a Shiny App) clicks on the number under 950000 and across from column 0.076 I want to select in Table 2 just this column 950000-0.076 - or ... %>% select(c("950000-0.076")). Which would return the following result:

# A tibble: 6 × 1
  `950000-0.076`
           <dbl>
1       -950000 
2         80000 
3         83400 
4         86922 
5         90570.
6       1387260.

How can I make a table "clickable" and reactive in Shiny?

Data:

table1 = structure(list(capRates = c(0.088, 0.084, 0.08, 0.076, 0.072), 
    `1100000` = c(0.0812, 0.0892, 0.0977, 0.1068, 0.1166), `1050000` = c(0.0928, 
    0.1009, 0.1095, 0.1187, 0.1285), `1000000` = c(0.1052, 0.1134, 
    0.122, 0.1313, 0.1412), `950000` = c(0.1185, 0.1267, 0.1354, 
    0.1447, 0.1547), `900000` = c(0.1327, 0.1409, 0.1497, 0.1591, 
    0.1692)), row.names = c(NA, -5L), class = "data.frame")

I also have the following table:

table2 = structure(list(`1100000-0.088` = c(-1100000, 80000, 83400, 86922, 
90570.06, 1210953.51814091), `1100000-0.084` = c(-1100000, 80000, 
83400, 86922, 90570.06, 1264125.19187143), `1100000-0.08` = c(-1100000, 
80000, 83400, 86922, 90570.06, 1322614.032975), `1100000-0.076` = c(-1100000, 
80000, 83400, 86922, 90570.06, 1387259.59419474), `1100000-0.072` = c(-1100000, 
80000, 83400, 86922, 90570.06, 1459087.99555), `1050000-0.088` = c(-1050000, 
80000, 83400, 86922, 90570.06, 1210953.51814091), `1050000-0.084` = c(-1050000, 
80000, 83400, 86922, 90570.06, 1264125.19187143), `1050000-0.08` = c(-1050000, 
80000, 83400, 86922, 90570.06, 1322614.032975), `1050000-0.076` = c(-1050000, 
80000, 83400, 86922, 90570.06, 1387259.59419474), `1050000-0.072` = c(-1050000, 
80000, 83400, 86922, 90570.06, 1459087.99555), `1000000-0.088` = c(-1000000, 
80000, 83400, 86922, 90570.06, 1210953.51814091), `1000000-0.084` = c(-1000000, 
80000, 83400, 86922, 90570.06, 1264125.19187143), `1000000-0.08` = c(-1000000, 
80000, 83400, 86922, 90570.06, 1322614.032975), `1000000-0.076` = c(-1000000, 
80000, 83400, 86922, 90570.06, 1387259.59419474), `1000000-0.072` = c(-1000000, 
80000, 83400, 86922, 90570.06, 1459087.99555), `950000-0.088` = c(-950000, 
80000, 83400, 86922, 90570.06, 1210953.51814091), `950000-0.084` = c(-950000, 
80000, 83400, 86922, 90570.06, 1264125.19187143), `950000-0.08` = c(-950000, 
80000, 83400, 86922, 90570.06, 1322614.032975), `950000-0.076` = c(-950000, 
80000, 83400, 86922, 90570.06, 1387259.59419474), `950000-0.072` = c(-950000, 
80000, 83400, 86922, 90570.06, 1459087.99555), `900000-0.088` = c(-900000, 
80000, 83400, 86922, 90570.06, 1210953.51814091), `900000-0.084` = c(-900000, 
80000, 83400, 86922, 90570.06, 1264125.19187143), `900000-0.08` = c(-900000, 
80000, 83400, 86922, 90570.06, 1322614.032975), `900000-0.076` = c(-900000, 
80000, 83400, 86922, 90570.06, 1387259.59419474), `900000-0.072` = c(-900000, 
80000, 83400, 86922, 90570.06, 1459087.99555)), class = c("tbl_df", 
"tbl", "data.frame"), row.names = c(NA, -6L))

Shiny App code:

library(shiny)
library(tidyverse)
library(reactable)



ui <- fluidPage(
  
  titlePanel("Old Faithful Geyser Data"),
  
  navbarPage("United",
             theme = shinythemes::shinytheme("cyborg"),
             tabPanel("IRR",
                      fluidRow(
                        column(6,
                               tags$h3("Table results"),
                               # tableOutput("TABLE1"),
                               reactableOutput("TABLE1")
                        ),
                        column(6,
                               tableOutput("TABLE2")
                        )
                      )
             )
  )
)


server <- function(input, output) {
  
  output$TABLE1 = renderReactable({
    reactable(table1, selection = "multiple", onClick = "select")
  })
  
    # output$TABLE1 = renderTable(
  #   table1
  # )

  
  # TABLE2 = reactive(
  #   table2 %>% 
  #     select(input$...)
  # )
   
}


shinyApp(ui = ui, server = server)

CodePudding user response:

I'd suggest adding a JavaScript function for onClick in order to get the column name and capRate value for the clicked cell as an input. So, table1's reactable would look like this:


reactable(table1,
          onClick = JS("
             function(rowInfo, colInfo) {
                Shiny.setInputValue('cell_data', colInfo.id   '-'   rowInfo.row.capRates, { priority: 'event' })
             }")
)

Practically, with colInfo.id we get the column name and with rowInfo.row.capRates the capRates value for the selected cell.

Then, table2 can be filtered by the value we passed on cell_data with the JS function.

output$TABLE2 = renderReactable({
    req(input$cell_data)
    reactable(table2 %>% select(sym(input$cell_data)))
 })

So, the app altogether would look like this:

library(shiny)
library(tidyverse)
library(reactable)

ui <- fluidPage(
  
  titlePanel("Old Faithful Geyser Data"),
  
  navbarPage("United",
             tabPanel("IRR",
                      fluidRow(
                        column(6,
                               tags$h3("Table results"),
                               reactableOutput("TABLE1")
                        ),
                        column(6,
                               reactableOutput("TABLE2")
                        )
                      )
             )
  )
)

server <- function(input, output) {
  
  output$TABLE1 = renderReactable({
    reactable(table1,
              onClick = JS("
              function(rowInfo, colInfo) {
                    Shiny.setInputValue('cell_data', colInfo.id   '-'   rowInfo.row.capRates, { priority: 'event' })
              }
            ")
    )
  })
  
  output$TABLE2 = renderReactable({
    req(input$cell_data)
    reactable(table2 %>% select(sym(input$cell_data)))
  })
  
}

shinyApp(ui = ui, server = server)
  • Related