Print the value of a selected cell from a datatable - r

I would like to extract the value of a selected cell instead of its row and column coordinates when I click on it as I want to use it as input for another procedure.
library(shiny)
library(DT)
data("mtcars")
ui <- shinyUI(
fluidRow(
DT::dataTableOutput("myDatatable"),
verbatimTextOutput("selectedCells")
)
)
server <- shinyServer(function(input, output, session) {
output$myDatatable <- DT::renderDataTable(mtcars,
selection=list(mode="single", target="cell"),
server = FALSE,
rownames=FALSE)
output$selectedCells <- renderPrint(input$myDatatable_cells_selected)
})
shinyApp(ui, server)

You can access the value in the table with row and column number like the following:
library(shiny)
library(DT)
data("mtcars")
ui <- shinyUI(fluidRow(
DT::dataTableOutput("myDatatable"),
verbatimTextOutput("selectedCells")
))
server <- shinyServer(function(input, output, session) {
output$myDatatable <- DT::renderDataTable(
mtcars,
selection = list(mode = "single", target =
"cell"),
server = FALSE,
rownames = FALSE
)
output$selectedCells <- renderPrint({
s = input$myDatatable_cells_selected
if (!is.null(s) && ncol(s) != 0) {
mtcars[s[1, 1] , s[1, 2] + 1]
} else {
NULL
}
})
})
shinyApp(ui, server)
As you can see, one must be added to column value to specify appropriate position. Handling unselected case is also important.

Related

Subset a data table based on cell selection of another datatable

I have a shiny app with 3 datatables. The first one contains only the 5th row with Species the 2nd table contains some random Species and the third table should get the selected cells from the first 2 tables and combines them into a new table. While the first seems to works fine the 2nd table selection seems to be wrong and that happens because it subsets by cell position and not by cell value.
library(shiny)
library(DT)
data("mtcars")
ui <- shinyUI(
fluidRow(
DT::dataTableOutput("myDatatable"),
DT::dataTableOutput("myDatatable2"),
DT::dataTableOutput("myDatatable3")
)
)
server <- shinyServer(function(input, output, session) {
output$myDatatable <- DT::renderDataTable(matrix(iris[,5]),
selection=list( target="cell"),
server = FALSE,
rownames=FALSE)
output$myDatatable2 <- DT::renderDataTable(matrix(iris[c(25,78,67,45,90,66,78,9,8),5]),
selection=list(mode="single", target="cell"),
server = FALSE,
rownames=FALSE)
output$myDatatable3 <- DT::renderDataTable(iris[c(input$myDatatable_cells_selected,input$myDatatable2_cells_selected),],
server = FALSE,
rownames=FALSE)
})
shinyApp(ui, server)
See code below. You were trying to subset the data versus creating a new dataframe(which from above sounds like what you want) + you want to use [tablename]_cell_clicked which has a row, column, value list versus [tablename]_cells_selected.
library(shiny)
library(DT)
data("mtcars")
ui <- shinyUI(
fluidRow(
DT::dataTableOutput("myDatatable"),
DT::dataTableOutput("myDatatable2"),
DT::dataTableOutput("myDatatable3")
)
)
server <- shinyServer(function(input, output, session) {
dat1 <- reactive({
matrix(iris[,5])
})
dat2 <- reactive({
matrix(iris[c(25,78,67,45,90,66,78,9,8),5])
})
dat3 <- reactive({
temp <- data.frame(results = c(input$myDatatable_cell_clicked$value, input$myDatatable2_cell_clicked$value))
})
output$myDatatable <- DT::renderDataTable(dat1(),
selection=list( target="cell"),
server = FALSE,
rownames=FALSE)
output$myDatatable2 <- DT::renderDataTable(dat2(),
selection=list(mode="single", target="cell"),
server = FALSE,
rownames=FALSE)
output$myDatatable3 <- DT::renderDataTable(dat3(),
server = FALSE,
rownames=FALSE)
})
shinyApp(ui, server)
**Updated based on OP's clarification
library(shiny)
library(DT)
data("mtcars")
ui <- shinyUI(
fluidRow(
DT::dataTableOutput("myDatatable"),
DT::dataTableOutput("myDatatable2"),
DT::dataTableOutput("myDatatable3")
)
)
server <- shinyServer(function(input, output, session) {
dat1 <- reactive({
matrix(iris[,5])
})
dat2 <- reactive({
matrix(iris[c(25,78,67,45,90,66,78,9,8),5])
})
dat3 <- reactive({
dat1row <- input$myDatatable_cells_selected
dat2row <- c(25,78,67,45,90,66,78,9,8)[c(input$myDatatable2_cell_clicked$row)]
temp <- iris[c(dat1row, dat2row),]
})
output$myDatatable <- DT::renderDataTable(dat1(),
selection=list( target="cell"),
server = FALSE,
rownames=FALSE)
output$myDatatable2 <- DT::renderDataTable(dat2(),
selection=list(mode="single", target="cell"),
server = FALSE,
rownames=FALSE)
output$myDatatable3 <- DT::renderDataTable(dat3(),
server = FALSE,
rownames=FALSE)
})
shinyApp(ui, server)

Inconsistent behavior during cell selection in DT datatable

I have the shiny app below in which the user clicks on a cell in the upper table and the relative cell should be displayed in the lower table. The issue is that when I unselect the cells in the upper the cells in the lower not only remain but become more.
library(shiny)
library(DT)
data("mtcars")
ui <- shinyUI(
fluidRow(
DT::dataTableOutput("myDatatable"),
DT::dataTableOutput("myDatatable2")
)
)
server <- shinyServer(function(input, output, session) {
dat1 <- reactive({
matrix(iris[,5])
})
list_all <- reactiveVal(character())
observeEvent(input$myDatatable_cell_clicked, {
list_all(append(list_all(), input$myDatatable_cell_clicked$value))
})
output$myDatatable <- DT::renderDataTable(dat1(),
selection=list( target="cell"),
server = FALSE,
rownames=FALSE)
output$myDatatable2 <- DT::renderDataTable(matrix(list_all()),
selection="none",
server = FALSE,
rownames=FALSE)
})
shinyApp(ui, server)
Please try below:
library(shiny)
library(DT)
data("mtcars")
ui <- shinyUI(
fluidRow(
DT::dataTableOutput("myDatatable"),
DT::dataTableOutput("myDatatable2")
)
)
server <- shinyServer(function(input, output, session) {
dat1 <- reactive({
matrix(iris[,5])
})
list_all <- reactiveVal(character())
observeEvent(input$myDatatable_cells_selected, {
if (nrow(input$myDatatable_cells_selected) == 0) {
list_all(character())
} else {
list_all(dat1()[input$myDatatable_cells_selected[,1]])
}
})
output$myDatatable <- DT::renderDataTable(dat1(),
selection=list( target="cell"),
server = FALSE,
rownames=FALSE)
output$myDatatable2 <- DT::renderDataTable(matrix(list_all()),
selection="none",
server = FALSE,
rownames=FALSE)
})
shinyApp(ui, server)
The main difference is using input$myDatatable_cells_selected which keeps the currently selected cells as opposed to input$myDatatable_cell_clicked which contains the clicked cell even when unselected, causing your issue.
Here is another version based on input$myDatatable_cells_selected using reactive over reactiveVal (should always be the preferred way in shiny) + this works for multiple columns.
library(shiny)
library(DT)
library(datasets)
ui <- shinyUI(fluidRow(
DT::dataTableOutput("myDatatable"),
DT::dataTableOutput("myDatatable2")
))
server <- shinyServer(function(input, output, session) {
dat1 <- reactive({
data.frame(iris[, 5])
})
selected <- reactive({
req(input$myDatatable_cells_selected)
selected <- input$myDatatable_cells_selected
selected[, 2] <- selected[, 2] + 1
return(selected)
})
output$myDatatable <- DT::renderDataTable(
dat1(),
selection = list(target = "cell"),
server = FALSE,
rownames = FALSE
)
output$myDatatable2 <- DT::renderDataTable(
data.frame(dat1()[selected()]),
selection = "none",
server = FALSE,
rownames = FALSE)
})
shinyApp(ui, server)

Store values based on multiple data table cell selection in a data frame

I have a shiny app with two data tables. The first one permits multiple cell selection while the 2nd one single. Every cell value should be stored inside list_all() and then displayed as a new table. The issue is that from the 1st table only the last cell selection is stored instead of every selection.
library(shiny)
library(DT)
data("mtcars")
ui <- shinyUI(
fluidRow(
DT::dataTableOutput("myDatatable"),
DT::dataTableOutput("myDatatable2"),
DT::dataTableOutput("myDatatable3")
)
)
server <- shinyServer(function(input, output, session) {
output$myDatatable <- DT::renderDataTable(matrix(iris[,5]),
selection=list( target="cell"),
server = FALSE,
rownames=FALSE)
output$myDatatable2 <- DT::renderDataTable(matrix(iris[c(25,78,67,45,90,66,78,9,8),5]),
selection=list(mode="single", target="cell"),
server = FALSE,
rownames=FALSE)
list_all <- reactive({
x <- c(input$myDatatable_cell_clicked$value, input$myDatatable2_cell_clicked$value)
})
output$myDatatable3 <- DT::renderDataTable(matrix(list_all())
)
})
shinyApp(ui, server)
Something like this?
library(shiny)
library(DT)
data("mtcars")
ui <- shinyUI(
fluidRow(
DTOutput("myDatatable"),
DTOutput("myDatatable2"),
DTOutput("myDatatable3")
)
)
server <- function(input, output, session) {
output$myDatatable <- renderDT(matrix(iris[,5]),
selection=list( target="cell"),
server = FALSE,
rownames=FALSE)
output$myDatatable2 <- renderDT(matrix(iris[c(25,78,67,45,90,66,78,9,8),5]),
selection=list(mode="single", target="cell"),
server = FALSE,
rownames=FALSE)
list_all <- reactiveVal(character())
observeEvent(input$myDatatable_cell_clicked, {
list_all(append(list_all(), input$myDatatable_cell_clicked$value))
})
observeEvent(input$myDatatable2_cell_clicked, {
list_all(append(list_all(), input$myDatatable2_cell_clicked$value))
})
output$myDatatable3 <- renderDT(matrix(list_all()))
}
shinyApp(ui, server)

RShiny: DT select rows and assign to group

I would like to give users an option to assign different rows (subjects) to groups.
Ideally, one can highlight rows, then write a group name in the "Assign to group: " field and it is saved. Then they can select a new set of rows and add those to a different group; and so on until all desired rows are assigned.
Here is what I have so far. I can't figure out how to save the results before selecting a new set of rows..
library(shiny)
library(DT)
ui <- fluidPage(
fluidRow(
column(6,
DT::dataTableOutput('x1'),
textInput("assignGroup","Assign to group: ")),
column(6, DT::dataTableOutput('x2'))
)
)
server <- shinyServer(function(input, output, session) {
output$x1 = DT::renderDataTable(cars, server = FALSE)
output$x2 = DT::renderDataTable({
s <- input$x1_rows_selected
temp <- cars
temp$Experiment <- as.character("")
temp[s,"Experiment"] <- input$assignGroup
temp
}, server = FALSE)
})
shinyApp(ui, server)
Thanks and hope this is somewhat clear!!!
You can observe 'input$x1_rows_selected' and then edit the table on the event. To display live changes to the table, you can add a reactive table.
Hope this code works out for you.
library(shiny)
library(DT)
ui <- fluidPage(
fluidRow(
column(6,
DT::dataTableOutput('x1'),
textInput("assignGroup","Assign to group: ")
),
column(6, DT::dataTableOutput('x2'))
)
)
server <- shinyServer(function(input, output, session) {
values <- reactiveValues(
df_data = cars,
temp = {
cars[,c("Experiment")]<-NA
cars
}
)
output$x1 = DT::renderDataTable(values$df_data, server = FALSE)
observeEvent(input$x1_rows_selected,
{
s<-input$x1_rows_selected
values$temp[s,"Experiment"]<-input$assignGroup
}
)
output$x2 = DT::renderDataTable(
values$temp, server = FALSE)
})
shinyApp(ui, server)

Output more than 1 datatables in shiny main panel

I have a shiny app that a user can check whether they want the data table displayed in the main panel. Depending on the numericinput, if they select 1, only 1 datatable be displayed or if they select 2 it will display 2 datatables I am not so sure how to code this in shiny R since I am new to this. Thank you for looking into this.
Here is my code
library("shiny")
df1 <- data.frame("2010-01"=double(),
"2010-02"=double(),
"2010-03"=double(),
"2010-04"=double()
)
df1<-rbind(df1,setNames(as.list(c(10,20,30,40)), names(df2)))
df2 <- data.frame("2010-01"=double(),
"2010-02"=double(),
"2010-03"=double(),
"2010-04"=double()
)
df2<-rbind(df2,setNames(as.list(c(100,200,300,400)), names(df2)))
df3 <- data.frame("2010-01"=double(),
"2010-02"=double(),
"2010-03"=double(),
"2010-04"=double()
)
df3<-rbind(df3,setNames(as.list(c(1000,2000,3000,4000)), names(df2)))
ui <-fluidPage(
sidebarPanel(
checkboxInput("add_data", "Add Data Table(s)"),
conditionalPanel(condition="input.add_data === true",
numericInput("numofdata",
label="Number of Data Table(s):",
min = 1,
max = 3,
value = 1,
step = 1),
uiOutput("num_of_data"),
textOutput("see_ranges")
),
actionButton("submit", "Submit")
),
mainPanel(
titlePanel("Output Data Table"),
DT::dataTableOutput("datatable.view", width = "95%")
) # end of main panel
)
server <- function(input, output, session) {
output$num_of_data <- renderUI({
lapply(1:input$numofdata, function(i) {
print(trend_list())
})
})
output$see_ranges <- renderPrint({
print(trend_list())
})
data.filter <- reactive({
df(i)
})
output$datatable.view <- DT::renderDataTable(
{
input$submit
if (input$submit==0) return()
isolate({
for(i in 1:input$numoftrends) {
datatable(data.filter(i),
rownames=FALSE,
extensions = c("FixedColumns", "FixedHeader", "Scroller"),
options = list(searching=FALSE,
autoWidth=TRUE,
rownames=FALSE,
scroller=TRUE,
scrollX=TRUE,
pagelength=1,
fixedHeader=TRUE,
class='cell-border stripe',
fixedColumns =
list(leftColumns=2,heightMatch='none')
)
)
}
})
})
}
shinyApp(ui = ui, server = server)
You should look at this article:
http://shiny.rstudio.com/gallery/creating-a-ui-from-a-loop.html
You will seen then that one has to create multiple renderDataTable instead of muliple datatable within one renderDataTable().
Also in your code you call df like a function df() but it is only defined as a variable.
See a generic running example below.
EDIT: Changed dynamic part of UI.
library(DT)
ui <- fluidPage(
sidebarLayout(
sidebarPanel(
selectInput("amountTable", "Amount Tables", 1:10, 3)
),
mainPanel(
# UI output
uiOutput("dt")
)
)
)
server <- function(input, output, session) {
observe({
lapply(1:input$amountTable, function(amtTable) {
output[[paste0('T', amtTable)]] <- DT::renderDataTable({
iris[1:amtTable, ]
})
})
})
output$dt <- renderUI({
tagList(lapply(1:input$amountTable, function(i) {
dataTableOutput(paste0('T', i))
}))
})
}
shinyApp(ui, server)

Resources