如何避免重复反应式代码?

问题描述 投票:0回答:1

我的应用程序需要多个输入(一些是固定的,一些是由用户定义的),并使用长而复杂的反应代码生成多个输出。输出存储在列表中以方便参考。 输出中是输入之一(其所有可能值)与输出之一的关系图。因此,我需要停止对这一输入的反应才能生成绘图。但我想避免重复 renderPlot() 内的长代码。关于如何实现这一目标有什么想法吗?

下面给出了绘制 y1 与 x1 的示例图。它应该帮助用户了解 x1 的什么值会产生所需的 y1,其他参数固定。 我用重复编写的完整应用程序:https://katrine.shinyapps.io/salmoncycleupd1/

library(shiny)
library(bslib)

#fixed parameters

a<-10
b<-20

ui <- page_sidebar (
  title = "updatable shiny1",
  sidebar = sidebar(
    
    sliderInput(
      "Input1",
      tags$strong("Define Input1"),
      min = 1,
      max = 15,
      value = 5,
      step = 1
    ),
    
        
    sliderInput(
      "Input2",
      tags$strong("Define Input2"),
      min = 100,
      max = 1000,
      value = 100,
      step = 100
    ),
    
        
    sliderInput(
      "Input3",
      tags$strong("Define Input3"),
      min = 7,
      max = 17,
      value = 12
      
    )
  ),
  
  tabPanel(tags$h4("Outputs"), 
           
           layout_columns(
             
             card(card_header(tags$span("Output1", style="color:tomato")),tableOutput("Output1")),
             card(card_header(tags$span("Output2", style="color:tomato")),tableOutput("Output2")),
             card(card_header(tags$span("Optimal", style="color:tomato")),plotOutput("Optimal")),
             
             
           )
)
)

server <- function(input, output) {
  
  mymodel <- reactive({
    
    x1 <- input$Input1
    x2 <- input$Input2
    x3 <- input$Input3
    
    #long and complex calculations
    
    y1 <- x1+x2+x3
    y2 <- x1*a
    y3 <- x2*b
    y4 <- x3+a+b
    
    # Store all results in a list for use in different tables
    
    list("y1" = y1, "y2" = y2, "y3" = y3, "y4" <- y4)
      
  })
  
  output$Output1 <- renderTable({
    
    table1 <- data.frame(matrix(ncol = 2, nrow = 2)) 
    colnames(table1) <- c("element1", "element2") 
    table1$element1 <- c(a, b)
    table1$element2 <- c(mymodel()$y1, mymodel()$y2)
    
    table1
    
        
  })
  
  output$Output2 <- renderTable({
    
    table2 <- data.frame(matrix(ncol = 2, nrow = 2)) 
    colnames(table2) <- c("element1", "element2") 
    table2$element1 <- c(a, b)
    table2$element2 <- c(mymodel()$y3, mymodel()$y4)
    
    table2
    
  })
  
  
  output$Optimal <- renderPlot({
    
    #plot y1 against x1, when x2 and x3 are still reactive 
    #x1 is no longer reactive
    
    x2 <- input$Input2
    x3 <- input$Input3
    
    optim <- function (x1) {  # have to copy parts from mymodel here, 
                               # cannot use y1 from the list as it is all reactive
      
      y1 <- x1+x2+x3
      
    }
    
    
    
    y1_range <- c(optim(1), optim(2), optim(3), optim(4), optim(5), optim(6), optim(7),optim(8), optim(9), optim(10), optim(11), optim(12), optim(13), optim(14), optim(15))
    x1_range <- c(1:15)
    
    plot(x1_range,y1_range, type="l", xlab="x1, other parameters fixed", ylab= "y1", col="darkgreen", lwd=2)
    
    
  })
  
}

shinyApp(ui = ui, server = server)

我研究过isolate()函数,但无法使其工作。

r shiny reactive
1个回答
0
投票

我尝试将函数与数据图中的反应数据分开。

注意两个错别字

  • 在列表中:
    "y4" = y4
    (原为
    "y4" <- y4
  • in
    optim()
    y1 <- x1+x2+x3
    在函数末尾不返回任何内容。
options(shiny.reactlog=TRUE) 
library(shiny)
library(bslib)

#fixed parameters

a<-10
b<-20

ui <- page_sidebar (
  title = "updatable shiny1",
  sidebar = sidebar(
    
    sliderInput(
      "Input1",
      tags$strong("Define Input1"),
      min = 1,
      max = 15,
      value = 5,
      step = 1
    ),
    
    
    sliderInput(
      "Input2",
      tags$strong("Define Input2"),
      min = 100,
      max = 1000,
      value = 100,
      step = 100
    ),
    
    
    sliderInput(
      "Input3",
      tags$strong("Define Input3"),
      min = 7,
      max = 17,
      value = 12
      
    )
  ),
  
  tabPanel(tags$h4("Outputs"), 
           
           layout_columns(
             
             card(card_header(tags$span("Output1", style="color:tomato")),tableOutput("Output1")),
             card(card_header(tags$span("Output2", style="color:tomato")),tableOutput("Output2")),
             card(card_header(tags$span("Optimal", style="color:tomato")),plotOutput("Optimal")),
             
             
           )
  )
)

server <- function(input, output) {
  
  MyComplexCalc <- function(x1 , x2, x3) {
    
    #long and complex calculations
    
    y1 <- x1+x2+x3
    y2 <- x1*a
    y3 <- x2*b
    y4 <- x3+a+b
    
    # Store all results in a list for use in different tables
    
    list("y1" = y1, "y2" = y2, "y3" = y3, "y4" = y4, 
         "x1" = x1, "x2" = x2, "x3" = x3)
    
  }
  
  
  
  mymodel <- reactive({
    
    MyComplexCalc(
      x1 = input$Input1,
      x2 = input$Input2,
      x3 = input$Input3
    )
    
    
  })
  
  output$Output1 <- renderTable({
    
    table1 <- data.frame(matrix(ncol = 2, nrow = 2)) 
    colnames(table1) <- c("element1", "element2") 
    table1$element1 <- c(a, b)
    table1$element2 <- c(mymodel()$y1, mymodel()$y2)
    
    table1
    
    
  })
  
  output$Output2 <- renderTable({
    
    table2 <- data.frame(matrix(ncol = 2, nrow = 2)) 
    colnames(table2) <- c("element1", "element2") 
    table2$element1 <- c(a, b)
    table2$element2 <- c(mymodel()$y3, mymodel()$y4)
    
    table2
    
  })
  
  
  y_DatasPlot <- reactive({
    
    optim <- function (x1,datas) { 
      
      
      MyComplexCalc(
        x1 = x1,
        x2 = datas$x2,
        x3 = datas$x3
      )$y1
      
    }
    
    datas2 <- mymodel()
    
    c(optim(1,datas2), optim(2,datas2), optim(3,datas2), optim(4,datas2), optim(5,datas2), optim(6,datas2), 
      optim(7,datas2),optim(8,datas2), optim(9,datas2), optim(10,datas2), optim(11,datas2), optim(12,datas2), 
      optim(13,datas2), optim(14,datas2), optim(15,datas2))
    
  })
  
  output$Optimal <- renderPlot({
    
    
    
    y1_range <- y_DatasPlot()
    
    x1_range <- c(1:15)
    
    plot(x1_range,y1_range, type="l", xlab="x1, other parameters fixed", ylab= "y1", col="darkgreen", lwd=2)
    
    
  })
  
}

shinyApp(ui = ui, server = server)

PS:您完整编写的应用程序具有非常干净的外观。

© www.soinside.com 2019 - 2024. All rights reserved.