UPDATE (18-Dec-2015) The currest best apporach for this problem is here: Get Selected Row From DataTable in Shiny App
======================
I am trying to reactively re-display a dataset using a row selection provided by the user. As a toy example,
ui.R
library(shiny)
shinyUI(pageWithSidebar(
headerPanel('Examples of DataTables'),
sidebarPanel(
checkboxGroupInput('show_vars', 'Columns to show:', names(mtcars),
selected = names(mtcars))
),
mainPanel(
dataTableOutput("mytable")
)
)
)
server.R
library(shiny)
shinyServer(function(input, output) {
# sorted columns are colored now because CSS are attached to them
output$mytable = renderDataTable({
addRadioButtons <- paste0('<input type="radio" name="row', 1:nrow(mtcars), '" value="', 1:nrow(mtcars), '">',"")
#Display table with radio buttons
cbind(Pick=addRadioButtons, mtcars[, input$show_vars, drop=FALSE])
}, options = list(bSortClasses = TRUE, aLengthMenu = c(5, 25, 50), iDisplayLength = 25))
})
I would like to use the radio button to collect the row number (say, row 4 in image above) from the user using some reactive expression, say rowSelect()
, and then dynamically re-display the table following some operation on the dataset, for example,
mtcars[mtcars[,1] > mtcars[rowSelect(),1], input$show_vars, drop=FALSE]
which would drop certain rows dynamically every time the user selects a row.
UPDATE (7-feb-14)
Incorporating the changes suggested by @Julien and implementing the method suggested by @Vincent, server.R becomes:
library(shiny)
shinyServer(function(input, output) {
#reactive row-selection
rowSelect <- reactive({
if(is.null(input[["row"]])) 1 #initialize
else as.numeric(input[["row"]])})
# User-selected sorting of dataset
output$mytable = renderDataTable({
addRadioButtons <- paste0('<input type="radio" name="row" value="', 1:nrow(mtcars), '">')
cbind(Pick=addRadioButtons, mtcars[order(mtcars[,1] - rnorm(nrow(mtcars), mtcars[rowSelect(),1])), input$show_vars, drop=FALSE])
}, options = list(bSortClasses = TRUE, aLengthMenu = c(5, 10, 20), iDisplayLength = 10))
})
As guessed by @agstudy, it was important to keep the number of rows in the datatable the same as before (not subsetting), hence the weird sorting operation above order(mtcars[,1] - rnorm(nrow(mtcars), mtcars[rowSelect(),1]))
.
UPDATE 2 (7-feb-14)
Anyway, this exercise does reveal a flaw in my example. My original intent was to use a separate covariance/similarity matrix to get the sorting order for the display datatable based on the user-selected row. Since the matrix and table would be very large, it didn't make sense to include them as drop-down input list or any other radiobutton input method in the side panel. It had to come from user-selection after displaying the whole datatable.
To achieve this, just replace the value
in the radiobutton with the unique row ID. In server.R, using the rowSelect()
expression (data
is the similarity matrix and meta
is the datatable displayed, ID
is the unique row identifier shared by data
and meta
):
addRadioButtons <- paste0('<input type="radio" name="row" value=', meta[order(data[rowSelect(),]),"ID"], '>')
cbind(Pick=addRadioButtons, meta[order(data[rowSelect(),]),input$show_vars])
This would keep resorting the datatable based on the user-selected row while choosing the order based on the similarity matrix via a unique row ID. Hope this helps someone.
But, if I use the rowSelect
reactive expression, then the row-selection based on a sorted datatable would not give me the correct row-selection for the similarity matrix (the order would have changed for the dataset but not for the matrix - recursion issue). This means that I would need to collect something other than a radio input of row number -- something more like an identifying row ID (which would match for both the table -- one of the columns -- and the matrix) using a form or a click submission -- along the lines of this: Selecting all text in HTML text input when clicked
Thanks for the help. @Vincent, your App is very cool. Hope to get there eventually. I will accept your answer.