问题
I am building a shiny datatable with one column for numericinput and the other reactive to the input. It is similar to what you can do in excel with equation embedded in cells. I am giving iris as example below and trying to calculate petal area. So peal area equals Petal.Length*Petal.Width/Adjust. The adjust parameter will be typed in by user to adjust area. A similar question was asked here but with no direct answer. Insert a numeric input for each row - R Shiny
library(shiny)
library(DT)
library(dplyr)
ui <- basicPage(
DT::dataTableOutput('x1')
)
server <- function(input, output, session) {
# create a character vector of shiny inputs
shinyInput = function(FUN, len, id, ...) {
inputs = character(len)
for (i in seq_len(len)) {
inputs[i] = as.character(FUN(paste0(id, i), label = NULL, ...))
}
inputs
}
# obtain the values of inputs
shinyValue = function(id, len) {
unlist(lapply(seq_len(len), function(i) {
value = input[[paste0(id, i)]]
if (is.null(value)) 1 else value
}))
}
# a sample data frame
DF <- reactive(
iris <- iris %>%
mutate(
adjust = shinyInput(numericInput, nrow(iris), 'adj', value = 1),
Petal_Area = Petal.Length*Petal.Width/shinyValue('adj', nrow(iris))
)
)
# render the table containing shiny inputs
output$x1 = DT::renderDataTable(
# use slider to control number of rows shown in table
DF(), server = FALSE, escape = FALSE, options = list(
preDrawCallback = JS('function() {
Shiny.unbindAll(this.api().table().node()); }'),
drawCallback = JS('function() {
Shiny.bindAll(this.api().table().node()); } ')
)
)
}
shinyApp(ui, server)
回答1:
This is an incomplete answer. In the hope that another user may be able to improve upon it. If not then this is the best possible answer.
I tried now for about half an hour but for some reason (maybe cause DT
is not meant to be used like Excel), I can't get the result of the calculation in the DT
-table. However reactivity and calculation work if I do not display the result in the DT
-table!
I only made two changes:
- I added a debugging table
- I replaced your
dplyr
-code and removed the calculation
The code looks like this:
library(shiny)
library(DT)
ui <- basicPage(
DT::dataTableOutput('x1'),
tableOutput('debug')
)
server <- function(input, output, session) {
# create a character vector of shiny inputs
shinyInput = function(FUN, len, id, ...) {
inputs = character(len)
for (i in seq_len(len)) {
inputs[i] = as.character(FUN(paste0(id, i), label = NULL, ...))
}
inputs
}
# obtain the values of inputs
shinyValue = function(id, len) {
unlist(lapply(seq_len(len), function(i) {
value = input[[paste0(id, i)]]
if (is.null(value)) 1 else value
}))
}
# a sample data frame
DF <- reactive({
iris_adj <- iris
iris_adj$adjust<-shinyInput(numericInput, nrow(iris), 'adj', value = 1)
# iris_adj$Petal_area<-iris$Petal.Length*iris$Petal.Width/shinyValue('adj',nrow(iris))
return(iris_adj)
})
# render the table containing shiny inputs
output$x1 <- DT::renderDataTable(
# use slider to control number of rows shown in table
DF(), server = FALSE, escape = FALSE, options = list(
preDrawCallback = JS('function() {
Shiny.unbindAll(this.api().table().node()); }'),
drawCallback = JS('function() {
Shiny.bindAll(this.api().table().node()); } ')
)
)
output$debug<-renderTable({
cbind(DF()[,-6],shinyValue('adj',nrow(iris)),Petal_Area=iris$Petal.Length*iris$Petal.Width/shinyValue('adj',nrow(iris)))
})
}
shinyApp(ui, server)
As soon as I add the calculation, output from the DT
does not find it's way into the debugging table.
On a personal note: I remember using this shinyInput
and shinyValue
trick about half a year ago. I also remember that it was very very unstable. I would not recommend it to anyone who wants to develop a stable app
I also remember that there was another R-package for complete interactive tables. It is called rhandsontables
. Maybe try that: https://jrowen.github.io/rhandsontable/
来源:https://stackoverflow.com/questions/50548785/r-shiny-datatable-with-numericinput-and-reactive-column