[英]In R shiny, how do you render a plot for a reactive object?
I've rendered plenty of plots in Shiny but this one is throwing me.我在 Shiny 中绘制了很多图,但这个让我很困惑。 When running the below MWE code, the default data.table is properly rendered in the main panel under the "Liabilities Module" tab.运行以下 MWE 代码时,默认的 data.table 会正确呈现在“负债模块”选项卡下的主面板中。 This data.table is the default view when first opening this tab.这个 data.table 是第一次打开这个标签时的默认视图。 See first image below to see what this looks like.请参阅下面的第一张图片以了解它的外观。
However, when I click on the "Vector plots" action button in that same "Liabilities Module" main panel, I get Error: need finite 'ylim' values as shown in the 2nd image below.但是,当我在同一个“负债模块”主面板中单击“矢量图”操作按钮时,出现错误:需要有限的“ylim”值,如下面的第二张图片所示。
The reactive object for rendering the data.table (which works as intended) and the plot (which doesn't work) is the same - vectorsAll
.用于呈现 data.table(按预期工作)和 plot(不工作)的反应式 object 是相同的 - vectorsAll
。
How do I plot the vectorsAll
object?我如何将vectorsAll
object? So that when the user clicks the "Vector plots" action button without having first clicked on the "Input Liabilities" action button in the sidebar panel, that same data from the default table is now plotted (value of 0.2 for 60 periods)?因此,当用户单击“矢量图”操作按钮而没有先单击侧边栏面板中的“输入负债”操作按钮时,现在会绘制默认表中的相同数据(60 个周期的值为 0.2)? Also, when the user clicks on the "Input Liabilities" action button and changes the value in row A of the matrix input grid, both the data.table and plot should update accordingly (the correct updating of the data.table based on the user changing the row A input matrix from 0.2 to 0.23 is shown in the 3rd image below).此外,当用户单击“输入负债”操作按钮并更改矩阵输入网格 A 行中的值时,data.table 和 plot 都应相应更新(根据用户更改 A 行正确更新 data.table从 0.2 到 0.23 的输入矩阵如下面的第三张图所示)。
I'd like to keep this in native Shiny, no ggplot or other plot package. I'll make this App fancier later as it progresses.我想将其保留在本机 Shiny 中,而不是 ggplot 或其他 plot package。随着它的进步,我会在稍后让这个应用程序更有趣。
MWE code: MWE代码:
library(shiny)
library(shinyMatrix)
library(shinyjs)
button2 <- function(x,y){actionButton(x,y,style="width:90px;margin-bottom:5px;font-size:80%")}
matrix1Input <- function(x){
matrixInput(x,
value = matrix(c(0.2), 4, 1,dimnames=list(c("A","B","C","D"),NULL)),
rows = list(extend=FALSE,names=TRUE),
cols = list(extend=FALSE,names=FALSE,editableNames=FALSE),
class = "numeric")}
pct <- function(x){paste(format(round(x*100,digits=1),nsmall=1),"%",sep="")} # convert to percentage
vectorBase <- function(x,y){
a <- rep(y,x)
b <- seq(1:x)
c <- data.frame(x = b, y = a)
return(c)}
ui <-
pageWithSidebar(
headerPanel("Model..."),
sidebarPanel(
fluidRow(helpText(h5(strong("Base Input Panel")),align="center",
style="margin-top:-15px;margin-bottom:5px")),
# Panels rendered with uiOuput & renderUI in server to stop flashing at invocation
uiOutput("Panels")
), # close sidebar panel
mainPanel(
tabsetPanel(
tabPanel("By balances", value=2),
tabPanel("By accounts", value=3),
tabPanel("Liabilities module", value=4,
fluidRow(h5(strong(helpText("Select model output to view:")))),
fluidRow(
button2('showVectorValueBtn','Vector values'),
button2('showVectorPlotBtn','Vector plots'),
), # close fluid row
div(style = "margin-top: 5px"),
# Shows outputs on each page of main panel
uiOutput('showResults')),
id = "tabselected"
) # close tabset panel
) # close main panel
) # close page with sidebar
server <- function(input,output,session)({
base_input <- reactive(input$base_input)
showResults <- reactiveValues()
yield <- function(){vectorBase(60,input$base_input[1,1])} # Must remain in server section
# --- Conditional panels rendered here rather than in UI to eliminate invocation flashing ------------>
output$Panels <- renderUI({
tagList(
conditionalPanel(
condition="input.tabselected==4",
actionButton('showLiabilityGrid','Input Liabilities',style='width:100%;background-color:LightGrey'),
setShadow(id='showLiabilityGrid'),
div(style = "margin-bottom: 10px"),
), # close conditional panel
conditionalPanel(condition="input.tabselected==3"),
conditionalPanel(condition="input.tabselected==4")
) # close tagList
}) # close renderUI
# --- Below defines the vectorsAll object before user clicks on actionButton "Input Liabilities" ---->
vectorsAll <- reactive({
if (is.null(input$showLiabilityGrid)){df <- NULL}
else {
if(input$showLiabilityGrid < 1){df <- cbind(Period = 1:60,Yld_Rate = pct(0.2))} # define what you want to display by default
else {
req(input$base_input)
df <- cbind(Period = 1:60,Yld_Rate = pct(yield()[,2]))
} # close 2nd else
} # close 1st else
df
}) # close reactive
output$table1 <- renderTable({vectorsAll()})
# --- Below produces vector values after clicking "Vector Values" button; see above for pre-click ---->
observeEvent(input$showVectorValueBtn,
{showResults$showme <-
tagList(tableOutput("table1"))
},ignoreNULL = FALSE)
# --- Below produces vector plots -------------------------------------------------------------------->
output$graph1 <-renderPlot(plot(vectorsAll()))
observeEvent(input$showVectorPlotBtn,{showResults$showme <- plotOutput("graph1")})
# --- Below sends both vector plots and vector values to UI section above ---------------------------->
output$showResults <- renderUI({showResults$showme})
# --- Below for modal dialog inputs ------------------------------------------------------------------>
observeEvent(input$showLiabilityGrid,
{showModal(modalDialog(
matrix1Input("base_input"),
div(style = "margin-top: 0px"),
useShinyjs(),
) # close modalDialog
) # close showModal
} # close showModal function
) # close observeEvent
}) # close server
shinyApp(ui, server)
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.