Блестящий реактивный работает только если вывести входные переменные - PullRequest
0 голосов
/ 25 декабря 2018

Я создаю Joyplot в одном из моих блестящих приложений.Это позволяет пользователям выбирать цвета заливки, используя radioGroupButtons.Здесь я сначала создаю график с помощью reactive, а затем использую реактивный вывод внутри renderPlot.Смотрите минимальный код, приведенный ниже.Проблема в том, что код внутри reactive выполняется только в том случае, если я печатаю входную переменную print(input$joy_plot_fill) (первая строка внутри реактива) .В противном случае нет.Буду признателен за любую помощь.

library(shiny)
library(shinyWidgets)
library(tidyverse)
library(viridis)
library(ggridges)
shinyApp(
  ui = 
    fluidPage(
      shinyWidgets::radioGroupButtons(
        inputId = "joy_plot_fill",
        label = "Fill choices", individual = T,
        choices = c("A" = "A", "B" = "B", "C" = "C", "D" = "D", "E" = "E"),
        selected = "C"
      ),

      plotOutput(outputId = "joyplot")
    ),

  server =
    function(input, output, session) {

      plot_data <- reactive({
        plot_data <- mtcars  %>% as_tibble() %>% dplyr::select(mpg,cyl,disp,hp,drat)
        plot_data_l <- plot_data %>% tidyr::gather(variable, value)
        return(plot_data_l) 

      })

      jp <- reactive({
        #print(input$joy_plot_fill)
        ggjoy_plot <- ggplot(plot_data()) +
          ggridges::stat_density_ridges(geom = "density_ridges_gradient" , 
                              mapping = aes(x = value, y = variable, fill = ..quantile..), 
                              calc_ecdf = TRUE , quantiles = 4, quantile_lines = T) +
          viridis::scale_fill_viridis(name = "Prob" , option = input$joy_plot_fill, discrete = T)
        return(ggjoy_plot)
      })

      output$joyplot <- renderPlot({
        jp()
      })

    }
)

===== ОБНОВЛЕНИЯ ==========

Изменение заполнения внутри ggridges::stat_density_ridges с..quantile.. до 0.5 - abs(0.5 - ..ecdf..), которые заполняют цвет по вероятности вместо квантилей, даже без строки print в reactive.Смотрите код ниже.Я не понимаю, как реагирующий блок получает предупреждение во втором сценарии, но не в первом.

    library(shiny)
library(shinyWidgets)
library(tidyverse)
library(viridis)
library(ggridges)
shinyApp(
  ui = 
    fluidPage(
      shinyWidgets::radioGroupButtons(
        inputId = "joy_plot_fill",
        label = "Fill choices", individual = T,
        choices = c("A" = "A", "B" = "B", "C" = "C", "D" = "D", "E" = "E"),
        selected = "C"
      ),

      actionButton("plot" , label = "Plot"),
      plotOutput(outputId = "joyplot")
    ),

  server =
    function(input, output, session) {

      plot_data <- reactive({
        plot_data <- mtcars  %>% as_tibble() %>% dplyr::select(mpg,cyl,disp,hp,drat)
        plot_data_l <- plot_data %>% tidyr::gather(variable, value)
        return(plot_data_l) 

      })

      jp <- reactive({
        #print(input$joy_plot_fill)
        ggjoy_plot <- ggplot(plot_data()) +
          ggridges::stat_density_ridges(geom = "density_ridges_gradient" , 
                              mapping = aes(x = value, y = variable,  fill = 0.5 - abs(0.5 - ..ecdf..)), 
                              calc_ecdf = TRUE) +
          viridis::scale_fill_viridis(name = "quantile" , option = input$joy_plot_fill, discrete = F)
        return(ggjoy_plot)
      })

      output$joyplot <- renderPlot({
        jp()
      })

    } 
)

1 Ответ

0 голосов
/ 25 декабря 2018

Использование -

shinyApp(
  ui = 
    fluidPage(
      shinyWidgets::radioGroupButtons(
        inputId = "joy_plot_fill",
        label = "Fill choices", individual = T,
        choices = c("A" = "A", "B" = "B", "C" = "C", "D" = "D", "E" = "E"),
        selected = "C"
      ),

      plotOutput(outputId = "joyplot")
    ),

  server =
    function(input, output, session) {

      plot_data <- reactive({
        plot_data <- mtcars  %>% as_tibble() %>% dplyr::select(mpg,cyl,disp,hp,drat)
        plot_data_l <- plot_data %>% tidyr::gather(variable, value)
        return(plot_data_l) 

      })

      output$joyplot <- renderPlot({
        ggplot(plot_data()) +
          ggridges::stat_density_ridges(geom = "density_ridges_gradient" , 
                                        mapping = aes(x = value, y = variable, fill = ..quantile..), 
                                        calc_ecdf = TRUE , quantiles = 4, quantile_lines = T) +
          viridis::scale_fill_viridis(name = "quantile" , option = input$joy_plot_fill, discrete = T)
      })

    }
)

Пояснение

Давайте сделаем понятие reactive простым.

В Shiny, естьВ реактивном программировании есть три типа объектов: реактивные источники, реактивные проводники и реактивные конечные точки

Источник - пользовательский ввод (input$joy_plot_fill в вашем случае).Реактивной конечной точкой обычно является то, что появляется в окне браузера пользователя, например, output$joyplot в вашем случае.

Так что, когда вы используете renderPlot для output$joyplot и передаете input$joy_plot_fill в качестве параметра, выпо сути, убедитесь, что он делает умный оптимизированный выбор, когда пытается воспроизвести сюжет.

Отличный ход: сделать plot_data реактивным, теперь , что называется реактивным проводником, но это имеет значение только в том случае, если данные велики, и вы не хотите больше их использоватьвремена, чем это абсолютно необходимо.

Обновление

Для проблемы print я попытаюсь объяснить.

Функция reactive по своей природе пытается выполнить какменьше как возможно.Если некоторые входные данные изменяются, реактивный блок срабатывает, если он обнаруживает зависимость от этого входа.

В вашем случае, когда вы передаете input$joy_plot_fill в качестве параметра функции ggplot, реактивный блок не может достичь этого кода и обнаружить изменение (так как это аргумент внутри функции).

Это не специфическая проблема печати.Попробуйте изменить строку печати на abcd <- input$joy_plot_fill - опять же, это ничего не делает, но каким-то образом это привлекает внимание реактива к этому компоненту ввода, поэтому он выполняется снова.

Попробуйте установить точку останова перед функцией jp и отладьте эту строку построчно, вы поймете, о чем я говорю.

Обновление 2

Я понял, что вы пытаетесь сказать, но, к сожалению, это почти невозможно объяснить.

Вот что будет определенно работать на вас.

  1. Перед запуском вашего блестящего приложения установите options(shiny.reactlog=TRUE)
  2. В случае, если работает (ecdf), запустите блестящее приложение, нажмите A, а затем нажмите Ctrl+F3.Это показывает график происхождения реактора.Здесь вы увидите, что каким-то образом необходимо пересчитать / переоценить выражение 0.5 - abs(0.5 - ..ecdf..), и поэтому график отображается, поскольку теперь существует прямая зависимость (я знаю, что это звучит расплывчато, но как только вы увидите график выполнения, вы поймете, что яговорить о)
  3. В случае, если это не работает (quantile), вы заметите, что ему почему-то не нужно выполнять оператор ggplot, так как все объекты кэшированы и ему не нужнопересчитать quantile.(Опять же, вы узнаете, как только увидите график)

Надеюсь, это поможет!Счастливого Рождества !!!

...