R:循环和IF语句内的选择性输出赋值

R:循环和IF语句内的选择性输出赋值,r,if-statement,while-loop,shiny,output,R,If Statement,While Loop,Shiny,Output,我有一个闪亮的应用程序,它调用一个脚本,在每次迭代中迭代生成一个图形。我需要显示每个绘图,并尝试使用recordPlot将每个绘图保存到列表中,并单独调用每个元素,但应用程序稍后无法识别对象。然后我还尝试在IF语句中包含不同的输出,但我的算法只为所有输出生成最后一个图,就像IF语句被忽略一样,我不知道如何处理它。以下是我的代码的简化: library(shiny) ui <- fluidPage( # Main panel for displaying outputs ----

我有一个闪亮的应用程序,它调用一个脚本,在每次迭代中迭代生成一个图形。我需要显示每个绘图,并尝试使用recordPlot将每个绘图保存到列表中,并单独调用每个元素,但应用程序稍后无法识别对象。然后我还尝试在IF语句中包含不同的输出,但我的算法只为所有输出生成最后一个图,就像IF语句被忽略一样,我不知道如何处理它。以下是我的代码的简化:

library(shiny)
ui <- fluidPage(
  # Main panel for displaying outputs ----
    mainPanel(
      actionButton("exec", "Start!!"),
      tagList(tags$h4("First iteration:")),
              plotOutput('PlotIter1'),
              tags$hr(),
              tagList(tags$h4("Second iteration:")),
              plotOutput('PlotIter2'),
              tags$hr(),
              tagList(tags$h4("Third iteration:")),
              plotOutput('PlotIter3'),
              tags$hr())
  )

server <- function(input, output) {
  ii <- 1
observeEvent(input$exec,{ 

  continue <- TRUE
  while(continue==TRUE){
    if(ii == 1){
      output$PlotIter1<-renderPlot({
        plot(rep(ii,50),main=ii)
      })
    }
    if(ii == 2){
      output$PlotIter2<-renderPlot({
        plot(rep(ii,50),main=ii)
      })
    }
    if(ii == 3){
      output$PlotIter3<-renderPlot({
        plot(rep(ii,50),main=ii)
      })
    }
    ii <- ii+1
    if(ii == 4){continue <- FALSE}
  }
  })
}

shinyApp(ui, server)
库(闪亮)

ui实际上,在使用
renderXXX
reactive
observe
内部循环时,可能会遇到一些问题,因为计算太慢。根据我的经验,最干净的解决方法是像这样使用lappy和loop-over


但是,对于您的情况,一个更快的解决方法是按照第一个答案中的建议使用
local
。请注意,
ii实际上,在使用
renderXXX
reactive
observe
内部循环时,可能会遇到一些问题,这是由于延迟计算造成的。根据我的经验,最干净的解决方法是像这样使用lappy和loop-over


但是,对于您的情况,一个更快的解决方法是按照第一个答案中的建议使用
local
。请注意,
iiI建议使用
,而
(或类似)回路缺少一些反应性电位。事实上,看起来您试图在shiny的依赖性/反应性层中强制绘制顺序

我认为应该有三个独立的块,在R/Shining允许的范围内同时迭代:

library(shiny)
ui <- fluidPage(
  # Main panel for displaying outputs ----
  mainPanel(
    actionButton("exec", "Start!!"),
    tagList(tags$h4("First iteration:")),
    plotOutput('PlotIter1'),
    tags$hr(),
    tagList(tags$h4("Second iteration:")),
    plotOutput('PlotIter2'),
    tags$hr(),
    tagList(tags$h4("Third iteration:")),
    plotOutput('PlotIter3'),
    tags$hr()
  )
)


server <- function(input, output) {
  output$PlotIter1 <- renderPlot({
    plot(rep(1,50),main=1)
  })
  output$PlotIter2 <- renderPlot({
    plot(rep(2,50),main=2)
  })
  output$PlotIter3 <- renderPlot({
    plot(rep(3,50),main=3)
  })
}

shinyApp(ui, server)

当然,这种方法只适用于曲线图相对一致且变化较小的情况。否则,上面的第一个版本可能更合适。

我建议使用
,而
(或类似)回路缺少一些反应潜力。事实上,看起来您试图在shiny的依赖性/反应性层中强制绘制顺序

我认为应该有三个独立的块,在R/Shining允许的范围内同时迭代:

library(shiny)
ui <- fluidPage(
  # Main panel for displaying outputs ----
  mainPanel(
    actionButton("exec", "Start!!"),
    tagList(tags$h4("First iteration:")),
    plotOutput('PlotIter1'),
    tags$hr(),
    tagList(tags$h4("Second iteration:")),
    plotOutput('PlotIter2'),
    tags$hr(),
    tagList(tags$h4("Third iteration:")),
    plotOutput('PlotIter3'),
    tags$hr()
  )
)


server <- function(input, output) {
  output$PlotIter1 <- renderPlot({
    plot(rep(1,50),main=1)
  })
  output$PlotIter2 <- renderPlot({
    plot(rep(2,50),main=2)
  })
  output$PlotIter3 <- renderPlot({
    plot(rep(3,50),main=3)
  })
}

shinyApp(ui, server)

当然,这种方法只适用于曲线图相对一致且变化较小的情况。否则,上面的第一个版本可能更合适。

对于将来的某个人来说,我最终提出的解决方案是将数据结构更改为一个列表,其中存储了每次迭代的结果,然后,列表中的每个元素在一个
周期内被绘制到相应的渲染图中。当然,如果没有埃文斯和塞西莉亚指出的非常重要的事情,这是不可能的。因此,这种方法提供了以下
server.R
功能:

server <- function(input, output){
  y <- list()
  #First data set
  y[[1]] <- rnorm(10,20,2)
  #Simple example of iteration results storage in the list simulating an iteration like procces
    for(i in 2:3){
    y[[i]]=y[[i-1]]+100
  }

  #Plots of every result
  for(j in 1:3){
  local({
    thisi <- j
    plotname <- sprintf("PlotIter%d", thisi)
    output[[plotname]] <<- renderPlot({
      plot(y[[thisi]], main=paste0("Iteration: ",thisi,", mean: ",round(mean(y[[thisi]]),2)
      ))
      abline(h=mean(y[[thisi]]),col=thisi)
    })
  })
  }
}

server对于未来的某个人,我最终提出的解决方案是将数据结构更改为一个列表,其中存储了每次迭代的结果,然后,列表中的每个元素都被绘制到
For
周期内相应的渲染图中。当然,如果没有埃文斯和塞西莉亚指出的非常重要的事情,这是不可能的。因此,这种方法提供了以下
server.R
功能:

server <- function(input, output){
  y <- list()
  #First data set
  y[[1]] <- rnorm(10,20,2)
  #Simple example of iteration results storage in the list simulating an iteration like procces
    for(i in 2:3){
    y[[i]]=y[[i-1]]+100
  }

  #Plots of every result
  for(j in 1:3){
  local({
    thisi <- j
    plotname <- sprintf("PlotIter%d", thisi)
    output[[plotname]] <<- renderPlot({
      plot(y[[thisi]], main=paste0("Iteration: ",thisi,", mean: ",round(mean(y[[thisi]]),2)
      ))
      abline(h=mean(y[[thisi]]),col=thisi)
    })
  })
  }
}

server感谢您的时间和努力,但是,也许我的MWE遇到了问题过于简单化的问题,因此第一种方法不适用于我的特定情况。第二个解决了我的问题。非常感谢。从你的问题和你接受的答案来看,你似乎只希望情节被完成一次,而且只有一次,永远不会更新。正确吗?是的,正确,我希望每次迭代都生成一个绘图,并以某种方式将该绘图存储在相应的渲染图中,以供以后显示。在任何情况下,尽管
local({})
解决方案在我的MWE上运行良好,但我的程序仍然在向我显示最后生成的绘图n倍于对应于相应迭代运行的绘图的开头。“for later show”对我来说没有意义。代码立即生成三个绘图,立即显示绘图,并且永远不会再次生成它们。这个“以后”的概念不符合我对它的看法。我理解您的实际用例可能与这个示例不同,所以我“了解”了更多的情况,但我并不完全遵循。(另外,我的答案对我有效;如果你说另一个答案对你的实际代码无效,那么也许你不应该接受它,而是编辑你的MWE/问题并重试?)可以忽略“供以后显示”部分,抱歉。我已经编辑了我的MWE和问题。谢谢你的时间和努力,但是,也许我的MWE遇到了问题过于简单化的问题,所以第一种方法不适用于我的特殊情况。第二个解决了我的问题。非常感谢。从你的问题和你接受的答案来看,你似乎只希望情节被完成一次,而且只有一次,永远不会更新。正确吗?是的,正确,我希望每次迭代都生成一个绘图,并以某种方式将该绘图存储在相应的渲染图中,以供以后显示。在任何情况下,尽管
local({})
解决方案在我的MWE上运行良好,但我的程序仍然在向我显示最后生成的绘图n倍于对应于相应迭代运行的绘图的开头。“for later show”对我来说没有意义。代码立即生成三个绘图,立即显示绘图,并且永远不会再次生成它们。这个“以后”的概念不符合我对它的看法。我理解您的实际用例可能与这个示例不同,所以我“了解”了更多的情况,但我并不完全遵循。(另外,我的答案对我有用;如果你说另一个答案对你的实际代码不起作用,那么也许你不应该接受它,而是编辑你的MWE/问题,然后再试一次
library(evaluate)

plotList <- list()
i <- 0

evaluate(
  function() {
    source("path/to/script.R")
  },
  output_handler = output_handler(
    graphics = function(plot) {
      i <- i + 1
      plotList[[i]] <- plot
    }
  )
)
library(shiny)
ui <- fluidPage(
  # Main panel for displaying outputs ----
  mainPanel(
    actionButton("exec", "Start!!"),
    tagList(tags$h4("First iteration:")),
    plotOutput('PlotIter1'),
    tags$hr(),
    tagList(tags$h4("Second iteration:")),
    plotOutput('PlotIter2'),
    tags$hr(),
    tagList(tags$h4("Third iteration:")),
    plotOutput('PlotIter3'),
    tags$hr()
  )
)


server <- function(input, output) {
  output$PlotIter1 <- renderPlot({
    plot(rep(1,50),main=1)
  })
  output$PlotIter2 <- renderPlot({
    plot(rep(2,50),main=2)
  })
  output$PlotIter3 <- renderPlot({
    plot(rep(3,50),main=3)
  })
}

shinyApp(ui, server)
server <- function(input, output) {
  for (i in 1:3) {
    local({
      thisi <- i
      plotname <- sprintf("PlotIter%d", thisi)
      output[[plotname]] <<- renderPlot({
        plot(rep(thisi, 50), main=thisi)
      })
    })
  }
}
server <- function(input, output){
  y <- list()
  #First data set
  y[[1]] <- rnorm(10,20,2)
  #Simple example of iteration results storage in the list simulating an iteration like procces
    for(i in 2:3){
    y[[i]]=y[[i-1]]+100
  }

  #Plots of every result
  for(j in 1:3){
  local({
    thisi <- j
    plotname <- sprintf("PlotIter%d", thisi)
    output[[plotname]] <<- renderPlot({
      plot(y[[thisi]], main=paste0("Iteration: ",thisi,", mean: ",round(mean(y[[thisi]]),2)
      ))
      abline(h=mean(y[[thisi]]),col=thisi)
    })
  })
  }
}