Блестящий в R: Как я могу затухать свой plotOutput из renderPlot, если определенные условия не выполняются?

вопрос прямой. Сначала я попробовал условие if-else на графике рендеринга. Что-то вроде

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

Это не сработало. Была показана серая область, в которой участок будет размещен позже, хотя условие еще не было выполнено. На следующем шаге я попытался использовать validate (см.Вот). Я в основном скопировал код из приведенного примера. Тем не менее, он по-прежнему показывает серую область, когда условие фактически не выполняется. Моя текущая попытка выглядит следующим образом:

ui.R

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

server.R

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

Функция сюжета только для иллюстрации. Мой выглядит по-другому. Любая помощь высоко ценится!

 Michal Majka20 июл. 2016 г., 12:50
ОК, есть несколько способов сделать это. Я опубликую некоторые решения через несколько часов, когда у меня будет свободное время.
 Patrick Balada20 июл. 2016 г., 12:54
@ Безымянный пользователь. Это очень щедро с вашей стороны! Большое спасибо. Я с нетерпением жду ваших отзывов.
 Patrick Balada20 июл. 2016 г., 12:47
@ Безымянный пользователь 8. Большое спасибо за комментарий. Это на самом деле именно то, что я хочу!
 Michal Majka20 июл. 2016 г., 12:38
Этот код работает только, если я удаляю внутреннюю функциюfunction(input, output) который является избыточным. Я тогда вижуsidebarPanel по умолчанию он серый и содержит невидимоеplotOutput (условие еще не выполнено) и кнопка. Что именно вы хотите? Хотите ли вы изначально только кнопку (нет места, зарезервированного для невидимого графика), и если она нажата, тоplotOutput должен исчезнуть?

Ответы на вопрос(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)
Решение Вопроса
Первая возможность - conditionalPanel

Мы хотим показатьplotOutput еслиactionButton был нажат. Более конкретно, еслиinput.Next > 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)
"Замедление поезда"

В этом примере мы собираемся «замедлить» ускорениеplotOutput, Для этого нам нужен пакетshinyjs.

Во-первых, мы собираемся обернутьconditionalPanel вdiv с идентификатором, скажем,animation

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

Затем на стороне сервера мы собираемся определить анимацию следующим образом: при условии ввода $ рядом, 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)
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)
 Michal Majka22 июл. 2016 г., 11:13
Итак, вас не волнует анимация, и вы хотите, чтобы сюжет появлялся одновременно с ползунком? (используя функцию renderUI) Мы можем думать о: D
 Michal Majka20 июл. 2016 г., 19:00
Ну, похоже, что умножениеinput.Next * 1 не нужно ... в любом случае: D
 Michal Majka22 июл. 2016 г., 11:32
Хорошо, я обновил пост :) Если вы хотите визуализировать больше, чем элемент сразу, вы должны заключить их в список
 Patrick Balada22 июл. 2016 г., 11:22
Я бы не сказал, что мне все равно ;-) Но это не главный приоритет. Сегодня утром мне удалось запустить график, используя функцию проверки, о которой я упоминал в своем вопросе. Работает очень плавно. Тем не менее, серая область (пространство, зарезервированное для графика) все еще отображается (как и следовало ожидать).
 Michal Majka22 июл. 2016 г., 11:44
Было приятно :) Кстати, я тоже поменял версию с условной панелью. Если вы рендерили ползунок с renderUI и plotOutput с условной панелью, возможно, они были отрисованы не одновременно. Теперь они появляются вместе, и вы всегда можете ускорить анимацию. Хорошего дня: D
 Patrick Balada22 июл. 2016 г., 11:41
Это идеально - именно то, что я искал! Спасибо за все усилия, которые вы приложили :-)
 Patrick Balada22 июл. 2016 г., 10:33
@ Безымянный пользователь. Большое спасибо за ваш обширный ответ! Очень приятно иметь пример того, как отложить plotOutput. Это действительно решает проблему, которая у меня была. Тем не менее, я заметил, что хочу также иметь некоторые ползунки ввода, которые должны повлиять на сюжет. Чтобы быть точным, я хочу иметь барплот, который изменяется при перемещении ручки слайдера. Я не уверен, является ли условная панель правильным выбором, потому что она задерживает весь процесс, что не очень хорошо. Я попытался включить график в renderUI, который создает слайдер, но это не работает.

Ваш ответ на вопрос