首页 > 解决方案 > 仅当打印输入变量时,闪亮的反应式才有效

问题描述

我正在我的一个闪亮的应用程序中创建 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..)printreactive

    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()
      })

    } 
)

标签: rshinyreactive

解决方案


利用 -

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在您的情况下。

因此,当您使用renderPlotforoutput$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。(再次,您将在看到图表后知道)

希望有帮助!圣诞节快乐!!!


推荐阅读