问题
This is somewhat of an expansion of this post:
I would like to have the DT::renderDataTable
inside the renderUI
and then have the output
of the renderUI
used in the reactive
.
This is what I'm doing:
suppressPackageStartupMessages(library(dplyr))
suppressPackageStartupMessages(library(plotly))
suppressPackageStartupMessages(library(shiny))
#data.frames to be used in the server
set.seed(1)
coordinate.df <- data.frame(coordinate_id = paste0("c", 1:1000),x = rnorm(1000), y = rnorm(1000), stringsAsFactors = F)
feature.df <- data.frame(coordinate_id = rep(paste0("c", 1:1000), 10), feature_id = rep(paste0("f", 1:10), 1000), value = rnorm(10*1000), stringsAsFactors = F)
feature.rank.df <- feature.df %>% dplyr::select(feature_id) %>% unique() %>% dplyr::mutate(rank=sample(1:10,10,replace = F)) %>% dplyr::arrange(rank)
feature.color.vec <- c("lightgray","darkred")
server <- function(input, output)
{
output$feature.idx <- renderUI({
output$feature.table <- DT::renderDataTable(feature.rank.df, server = FALSE, selection = "single")
DT::dataTableOutput("feature.table")
})
feature.plot <- reactive({
if(!is.null(input$feature.idx)){
feature.id <- feature.rank.df$feature_id[input$feature.idx]
plot.title <- feature.id
plot.df <- suppressWarnings(feature.df %>%
dplyr::filter(feature_id == feature.id) %>%
dplyr::left_join(coordinate.df,by = c("coordinate_id"="coordinate_id")))
feature.plot <- suppressWarnings(plotly::plot_ly(marker=list(size=3),type='scatter',mode="markers",color=plot.df$value,x=plot.df$x,y=plot.df$y,showlegend=F,colors=colorRamp(feature.color.vec)) %>%
plotly::layout(title=plot.title,xaxis=list(zeroline=F,showticklabels=F,showgrid=F),yaxis=list(zeroline=F,showticklabels=F,showgrid=F)) %>%
plotly::colorbar(limits=c(min(plot.df$value,na.rm=T),max(plot.df$value,na.rm=T)),len=0.4,title="Value"))
}
feature.plot
})
output$outPlot <- plotly::renderPlotly({
feature.plot()
})
}
ui <- fluidPage(
titlePanel("Results Explorer"),
sidebarLayout(
sidebarPanel(
uiOutput("feature.idx")
),
mainPanel(
plotly::plotlyOutput("outPlot")
)
)
)
shinyApp(ui = ui, server = server)
It does load the feature.rank.df
data.frame
but it then prints this error message to the main panel:
Error: no applicable method for 'plotly_build' applied to an object of class "c('reactiveExpr', 'reactive')"
And nothing gets plotted upon row selection in the table in the side panel.
Any idea what the solution is?
回答1:
You can fix this by replacing your server function by the code below.
- refer to the selected feature by
input$feature.table_rows_selected
- keep the reactive feature.plot code in the
renderPlotly
function
server <- function(input, output)
{
output$feature.idx <- renderUI({
output$feature.table <-
DT::renderDataTable(feature.rank.df,
server = FALSE,
selection = "single")
DT::dataTableOutput("feature.table")
})
output$outPlot <- plotly::renderPlotly({
if (!is.null(input$feature.table_rows_selected)) {
feature.id <-
feature.rank.df$feature_id[input$feature.table_rows_selected]
plot.title <- feature.id
plot.df <- suppressWarnings(
feature.df %>%
dplyr::filter(feature_id == feature.id) %>%
dplyr::left_join(
coordinate.df,
by = c("coordinate_id" = "coordinate_id")
)
)
feature.plot <-
suppressWarnings(
plotly::plot_ly(
marker = list(size = 3),
type = 'scatter',
mode = "markers",
color = plot.df$value,
x = plot.df$x,
y = plot.df$y,
showlegend = F,
colors = colorRamp(feature.color.vec)
) %>%
plotly::layout(
title = plot.title,
xaxis = list(
zeroline = F,
showticklabels = F,
showgrid = F
),
yaxis = list(
zeroline = F,
showticklabels = F,
showgrid = F
)
) %>%
plotly::colorbar(
limits = c(
min(plot.df$value, na.rm = T),
max(plot.df$value, na.rm = T)
),
len = 0.4,
title = "Value"
)
)
feature.plot
}
})
}
Edit:
Alternatively, you can keep the feature.plot as a reactive, like this:
server <- function(input, output)
{
output$feature.idx <- renderUI({
output$feature.table <- DT::renderDataTable(feature.rank.df, server = FALSE, selection = "single")
DT::dataTableOutput("feature.table")
})
feature.plot <- reactive({
if (!is.null(input$feature.table_rows_selected)) {
feature.id <-
feature.rank.df$feature_id[input$feature.table_rows_selected]
plot.df <- suppressWarnings(
feature.df %>%
dplyr::filter(feature_id == feature.id) %>%
dplyr::left_join(coordinate.df, by = c("coordinate_id" =
"coordinate_id"))
)
feature.plot <-
suppressWarnings(
plotly::plot_ly(
marker = list(size = 3),
type = 'scatter',
mode = "markers",
color = plot.df$value,
x = plot.df$x,
y = plot.df$y,
showlegend = F,
colors = colorRamp(feature.color.vec)
) %>%
plotly::layout(
title = plot.df$feature_id[1],
xaxis = list(
zeroline = F,
showticklabels = F,
showgrid = F
),
yaxis = list(
zeroline = F,
showticklabels = F,
showgrid = F
)
) %>%
plotly::colorbar(
limits = c(
min(plot.df$value, na.rm = T),
max(plot.df$value, na.rm = T)
),
len = 0.4,
title = "Value"
)
)
}
return(feature.plot)
})
output$outPlot <- plotly::renderPlotly({
req(feature.plot(), input$feature.table_rows_selected)
feature.plot()
})
}
来源:https://stackoverflow.com/questions/61493318/combining-renderui-datatableoutput-renderdatatable-and-reactive