【问题标题】:Shiny in R: How can I fade-out my plotOutput from renderPlot if certain conditions are not met?R 中的闪亮:如果不满足某些条件,如何从 renderPlot 中淡出我的 plotOutput?
【发布时间】:2016-07-22 17:41:23
【问题描述】:

问题是直截了当的。首先,我在渲染图中尝试了 if-else 条件。类似的东西

if (input$Next > 0) {
   plot(...)
}
else {
   return()
}

这不起作用。即使尚未满足条件,也会显示稍后放置绘图的灰色区域。 在下一步中,我尝试使用 validate(请参阅 here)。我基本上从给定示例中复制了代码。但是,当实际不满足条件时,它仍然显示灰色区域。我目前的尝试如下:

ui.R

shinyUI(fluidPage(
   sidebarPanel(
      plotOutput("test"),
      actionButton("Next", "Next")
))

服务器.R

shinyServer(function(input, output, session) {
function(input, output) {
  output$test <- renderPlot({
     validate(
        need(input$Next > 0)
     )
     pt <- plot(input$Next,2)
     print(pt)
  })
}
})

绘图功能仅用于说明。我的看起来不一样。非常感谢任何帮助!

【问题讨论】:

  • 此代码仅在我删除多余的内部函数 function(input, output) 时才有效。然后我看到默认为灰色的sidebarPanel,它包含一个不可见的plotOutput(尚未满足条件)和一个按钮。你到底想要什么?您最初是否只想要按钮(不为不可见的绘图保留空间),如果按下它,那么 plotOutput 应该淡入吗?
  • @UnnamedUser 8。非常感谢您的评论。这其实正是我想要的!
  • 好的,有几种方法可以做到这一点。有空我会在几个小时后发布一些解决方案。
  • @UnnamedUser。你真是太慷慨了!非常感谢。我期待着您的意见。

标签: r shiny


【解决方案1】:
  1. 第一种可能性 - conditionalPanel

如果按下了actionButton,我们希望显示plotOutput。更具体地说,如果input.Next &gt; 0。此条件在javaScript 中进行评估,因此我们的语法略有不同——我们在输入后使用. 而不是$,并使用括号。

conditionalPanel(
      condition = "input.Next * 1 > 0",
      plotOutput("test")  
    )

然而,我们将input.Next 乘以一是很奇怪的。这是必要的,因为input.Next 期望一个数字,也返回属性。似乎 JavaScript 不知道如何处理这个问题……但是乘法可以解决问题。

[1] 0
attr(,"class")
[1] "integer"                "shinyActionButtonValue"

在此示例中,plotOutput立即出现...肯定太快了。

library(shiny)

ui1 <- shinyUI(fluidPage(
  sidebarPanel(
    conditionalPanel(
      condition = "input.Next * 1 > 0",
      plotOutput("test")  
    ),
    actionButton("Next", "Next")
  )
))


server1 <- shinyServer(function(input, output, session) {

  output$test <- renderPlot({
    pt <- plot(input$Next, 2)
    print(input$Next)
    print(pt)
  })

})

shinyApp(ui1, server1)

  1. "Slowing down the train"

在本例中,我们将“减慢”超速行驶的plotOutput。为此,我们需要 shinyjs 包。

首先,我们要将conditionalPanel 包装成一个带有ID 的div,例如animation

div(id = "animation",
      conditionalPanel(
        condition = "input.Next * 1 > 0",
        plotOutput("test")  
      )
    )

然后,在服务器端,我们将按以下方式定义动画:以输入为条件$next div 应该与幻灯片动画一起显示。

observe({
        toggle(id = "animation", anim = TRUE, animType = "slide",
              time = 0.5, condition = input$Next > 0)
      })

 

完整示例:

ui2 <- shinyUI(fluidPage(
  # we need to include this function in order to use shinyjs functions
  useShinyjs(), 

  sidebarPanel(
    actionButton("Next", "Next"), 

    div(id = "animation",
        conditionalPanel(
          condition = "input.Next * 1 > 0",
          plotOutput("test"),
          sliderInput("manipulate", "slider", min = 0, max = 1, value = 1)
        )
    )
  )
))


server2 <- shinyServer(function(input, output, session) {

  # Introduce gently the div with an id = "animation" and its all content.
  observe({
    toggle(id = "animation", anim = TRUE, animType = "slide",
           time = 0.5, condition = input$Next > 0)
  })
  # We could animate only the plotOutput with "toogle(id = test")" 
  # - it would work as well, but for the first time the plot is shown
  # way we would get an errors with margins.


  output$test <- renderPlot({
    #plot(input$Next, 2)
    ggplot(iris, aes(x = Species)) + geom_bar(alpha = input$manipulate)

  })
})

shinyApp(ui2, server2)

  1. renderUI

正如您所指出的,另一种可能性是使用函数renderUI。如果您想一次渲染多个元素,则必须将它们包装到 list 中,如下例所示:

library(shiny)
library(ggplot2)

ui3 <- shinyUI(fluidPage(
  sidebarPanel(
    uiOutput("dynamic"),
    actionButton("Next", "Next")
  )
))


server3 <- shinyServer(function(input, output, session) {

  output$dynamic <- renderUI({
    if (input$Next > 0) {
      # if we want to render more element, we need the list
      list(
        plotOutput("test"),
        sliderInput("manipulate", "slider", min = 0, max = 1, value = 1)
      )
    }
  })


  output$test <- renderPlot({
    #plot(input$Next, 2)
    ggplot(iris, aes(x = Species)) + geom_bar(alpha = input$manipulate)
  })

})

shinyApp(ui3, server3)

【讨论】:

  • 好吧,看来input.Next * 1 的乘法是不必要的......无论如何:D
  • @UnnamedUser。非常感谢您的广泛回答!有一个如何延迟 plotOutput 的示例非常好。这真的解决了我遇到的问题。但是,我注意到我还想有一些滑块输入,这应该会影响情节。准确地说,我想要一个条形图,它随着滑块手柄的移动而变化。我不确定条件面板是否是正确的选择,因为它会延迟整个过程,这不好。我试图将绘图包含在生成滑块的 renderUI 中,但这不起作用。
  • 那么,您不关心动画并希望情节同时出现滑块? (使用renderUI函数)我们可以考虑:D
  • 好的,我已经更新了帖子 :) 如果你想一次渲染多个元素,你必须将它们包装到一个列表中
  • 我很高兴 :) 顺便说一句,我也用条件面板更改了版本。如果您使用 renderUI 渲染滑块并使用条件面板渲染 plotOutput,则它们可能不是同时渲染的。现在,它们一起出现,您也可以随时加快动画速度。祝你有美好的一天:D
【解决方案2】:

像这样使用条件面板:

library(shiny)
ui =fluidPage(
  sidebarPanel(
    conditionalPanel(condition="input.Next>0",
    plotOutput("test")),
    actionButton("Next", "Next")
  ))

server=shinyServer(function(input, output, session) {

    output$test <- renderPlot({

        req(input$Next > 0)

      pt <- plot(input$Next,2)
      print(pt)
    })

})

shinyApp(ui=ui,server=server)

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2015-10-18
    • 2016-10-12
    • 1970-01-01
    • 1970-01-01
    • 2018-01-09
    • 2013-01-06
    相关资源
    最近更新 更多