R Shiny:在plotOutput中创建非反应性背景

2024-04-08

我正在尝试构建一个闪亮的应用程序,我可以在其中交互式地更改绘图。我希望绘图在几毫秒内发生变化,并且由于变化仅包括添加一些点,这实际上是可能的。

可重现的示例包含此想法的抽象。第一个示例绘制了一个散点图,我可以交互地更改点数。这基本上立即发生。我将这部分图称为“反应层”。

library(shiny)

ui <- fluidPage(
  
  sliderInput(inputId = "slider_input", label = "Reactive values:", min = 1, max = 100, value = 10),
  plotOutput(outputId = "plotx")
  
)

quick_server <- function(input, output, session){
    
  output$plotx <- renderPlot({
    
    # reactive layer
    plot(
      x = sample(x = -4:4, size = input$slider_input, replace = T), 
      y = sample(x = -4:4, size = input$slider_input, replace = T)
      )
    
  })
  
}

shinyApp(ui = ui, server = quick_server)

问题是,我想要交互式更改的图始终包含许多数据点的“缓慢非反应层”,这些数据点不反应并且永远不会改变。由于该数据集的大小以及renderPlot()总是重新绘制它,我交互式地改变“反应层”的速度急剧下降。

library(shiny)

ui <- fluidPage(
  
  sliderInput(inputId = "slider_input", label = "Reactive values:", min = 1, max = 100, value = 10),
  plotOutput(outputId = "plotx")
  
)

slow_server <- function(input, output, session){
  
  base_data <- reactiveVal(value = data.frame(x = rnorm(n = 200000), y = rnorm(n = 200000)))
  
  output$plotx <- renderPlot({
    
    # slow non reactive layer
    plot(x = base_data()$x, y = base_data()$y)
    
    # reactive layer
    points(
      x = sample(x = -4:4, size = input$slider_input, replace = T),
      y = sample(x = -4:4, size = input$slider_input, replace = T), 
      col = "red", 
      cex = 5, 
      pch = 19
      )
    
  })
  
}

shinyApp(ui = ui, server = slow_server)

由于基础数据和结果图(这里是点云)永远不会改变,这是相当令人烦恼的renderPlot()总是重新绘制所有内容(两个“层”)。有没有办法“隔离”从非反应数据集创建的图?这样不具有反应性的层就不会被重新绘制?

我已经尝试使用 ggplot2 并创建一个稳定的层

big_data_frame <- data.frame(x = rnorm(n = 200000), y = rnorm(n = 200000))

steady_layer <- reactiveVal(value = geom_point(data = big_data_frame, mapping = aes(x = x, y = y))

然后创建这样的情节

output$plotx <- renderPlot({

  small_df <- 
   data.frame(
      x = sample(x = -4:4, size = input$slider_input, replace = T),
      y = sample(x = -4:4, size = input$slider_input, replace = T)
    )
  
   ggplot() + 
    steady_layer() +
    geom_point(data = small_df, mapping = aes(x = x, y = y) 
    
})


但这并没有帮助,因为重新绘制过程需要时间而不是创建 ggplot 图层本身。

尽管我可以想象解决方案可能是创建大图的 .png 并将其用作 HTML 和 CSS 的背景output$plotx通过使其成为反应式 UI,我无法成功操作 HTML 和 CSS。

任何帮助表示赞赏。非常感谢!


你需要了解如何renderPlot作品。它使用 Rpng函数首先创建一个png,然后将其发送到客户端浏览器。当绘图的数据发生变化时,会重新创建此 png。因此,重新绘制 png 的一部分是不可能的。因此,向现有绘图添加点将始终使用slow points + new points,所以在目前的shiny机制下,不重新计算这些慢点是不可能的。一个可能的选择是使用plotly with proxy https://plotly-r.com/linking-views-with-shiny.html。它由 HTML 和 Javascript 组成,所以是的,您可以通过部分更新来完成。详细内容见链接,此处不再赘述。就我个人的经验来说,它的速度不是你想要的那么快到毫秒级。

所以我在这里给你一个聪明的技巧:为什么我们要在同一个地块上更新?我们可以使用一张图作为背景,虽然速度很慢,但我们只渲染一次,而且我们永远不会再碰它。然后我们更新另一个只有几个点的图,并将该图堆叠在慢速图的顶部。

具体方法如下:

  1. 添加一些 CSS 技巧来进行堆叠
  2. 渲染缓慢的情节
  3. 以透明度渲染快速绘图
library(shiny)
library(ggplot2)
ui <- fluidPage(
    
    sliderInput(inputId = "slider_input", label = "Reactive values:", min = 1, max = 100, value = 10),
    div(
        class = "large-plot",
        plotOutput(outputId = "plot_bg"),
        plotOutput(outputId = "plotx")
    ),
    tags$style(
        "
        .large-plot {
            position: relative;
        }
        #plot_bg {
            position: absolute;
        }        
        #plotx {
            position: absolute;
        }
        "
    )
    
    
)

slow_server <- function(input, output, session){
    
    base_data <- reactiveVal(value = data.frame(x = rnorm(n = 200000), y = rnorm(n = 200000)))
    
    output$plot_bg <- renderPlot({
        ggplot(base_data()) +
            geom_point(aes(x,y)) +
            scale_x_continuous(breaks = -4:4) +
            scale_y_continuous(breaks = -4:4) +
            xlim(-5, 5) +
            ylim(-5, 5)
    })
    output$plotx <- renderPlot({
        data.frame(
            x = sample(x = -4:4, size = input$slider_input, replace = T),
            y = sample(x = -4:4, size = input$slider_input, replace = T)
        ) %>% 
            ggplot() +
                geom_point(aes(x,y), color = "red", size = 3) + 
                scale_x_continuous(breaks = -4:4) +
                scale_y_continuous(breaks = -4:4) +
            theme(
                panel.background = element_rect(fill = "transparent"),
                plot.background = element_rect(fill = "transparent", color = NA), 
                panel.grid.major = element_blank(), 
                panel.grid.minor = element_blank(), 
                legend.background = element_rect(fill = "transparent"), 
                legend.box.background = element_rect(fill = "transparent")
            )+
            xlim(-5, 5) +
            ylim(-5, 5)
    }, bg="transparent")
    
}

shinyApp(ui = ui, server = slow_server)
本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

R Shiny:在plotOutput中创建非反应性背景 的相关文章

  • R中的字典数据结构

    在 R 中 我有 例如 gt foo lt list a 1 b 2 c 3 如果我输入foo I get a 1 1 b 1 2 c 1 3 我怎样才能看透foo仅获取 键 列表 在这种情况下 a b c R 列表可以具有命名元素 因此可
  • 将字符串列拆分为多个虚拟变量

    作为 R 中 data table 包的相对缺乏经验的用户 我一直在尝试将一个文本列处理为大量指示符列 虚拟变量 每列中的 1 表示特定的子字符串是在字符串列中找到 例如我想处理这个 ID String 1 a b 2 b c 3 c 进入
  • Android:使 Dialog 周围的所有内容都比默认值更暗

    我有一个具有以下样式的自定义对话框 它显示了一个无边框对话框 后面的任何内容都会 稍微 变暗 我的设计师希望背后的一切都比 Android 的默认设置更暗 但不是完全黑色 有这样的设置吗 我能想到的唯一解决方法是使用全屏活动而不是对话框 只
  • 使用officer R导出时如何提高ggplots的分辨率

    我想将图表导出到 PPT 并使用Officer 包来实现相同的目的 但是 图表的默认分辨率较低 我想更改它 我目前正在使用以下电话 ph with gg p1 type chart res 1200 其中 p1 是 ggplot 对象 运行
  • 需要在R中按行绑定列表数据

    我在 R 中按行绑定列表时遇到问题 我的列表数据集是 id 1 data k 1 id k b c 1 1 1 3 data k 2 id k b c 1 2 1 4 id 2 data k 1 id k b c 2 1 1 6 data
  • 如何按时间间隔匹配数据帧?

    这是我从数据记录器导入原始数据时经常出现的问题 温度记录仪设置为每十分钟记录一次温度 单独的气体记录仪设置为记录最后十分钟间隔内使用的气体 我想将这两个记录器的数据合并到一个数据框中进行绘图和分析 但时间并不完全一致 我希望每十分钟的时间段
  • 如何纠正 data.frame 上的字符编码

    我有一个像这样的数据框 data names lt data frame DATA c 1 5 rownames data names lt c IV xc1N JOS xc9 LUC xcdA RAM xd3N TO xd1O data
  • 多个动态滤镜更新闪亮

    我希望能够让 UI 输入闪亮 并根据用户之前的选择进行自我更新 因此 在下面的示例中 预期的行为是用户选择cyl vsor carb那么这将 过滤数据集mtcars用于创建绘图 即用户根据过滤条件调整绘图并 更新其他过滤器中的剩余输入选择
  • 为什么 sapply 的缩放速度比样本大小的 for 循环慢?

    假设我想采用向量 X 2 1 N 并将 e 计算为每个元 素的指数 是的 我认识到最好的方法就是通过向量化 exp X 但这样做的目的是将 for 循环与 sapply 进行比较 我通过逐步尝试三种方法 一种使用 for 循环 两种以不同方
  • 如何在 R 中的 for 循环内将值存储在向量中

    我正在开始使用 R 但我对以下问题感到非常沮丧 我试图将 for 循环内完成的某些计算的值存储到我之前定义的向量中 问题是如何进行索引 因为for循环迭代代码的次数取决于用户的输入 所以变量i不一定要从1开始 它可以从80开始 for举个例
  • `dplyr::_join` 函数的命名向量“by”参数[重复]

    这个问题在这里已经有答案了 我正在写一个函数dplyr join两个数据框by不同的列 第一个数据帧的列名称动态指定为函数参数 我相信我需要使用rlang准引用 元编程 但未能找到可行的解决方案 我很感激任何建议 library dplyr
  • 在 R 的 for 循环中创建动态命名对象并分配动态值

    我正在尝试创建一套动态命名的新对象 例如 temp2015 使用 for 循环 并存储动态值 具体来说 其他对象的名称 例如 Y2015 和 for 循环中使用的值 例如 2015 在动态命名的新对象中 我不确定为什么下面的代码不起作用 Y
  • 在 Shiny 中显示反应式 htmlTable 表格

    我正在制作我的第一个 Shiny 应用程序 但找不到任何有关如何显示使用 htmlTable 包创建的表格的示例 我基本上想在按下按钮时创建一个表格并显示它 Shiny 显示 html 代码而不是表格 我不知道用什么替换服务器部分中的 re
  • 在 R 中提取 data.frames 列表的名称以及 data.frame 中的值

    在下面的代码中 j是 data frames 的命名列表 我想知道是否有办法 a 提取变量的数值 即one short and one long 在 data frames 内并附加它们的相关名称 即 AAA or BBB or CCC 到
  • R在Windows平台Rstudio上打印data.frames中的UTF-8代码

    当数据框中存在UTF 8字符时 将无法正常显示 例如 以下内容是正确的 gt U6731 1 朱 但是当我将其放入数据框中并打印出来时 它是 gt data frame x U6731 x 1
  • R:按组,测试一个变量的每个值是否存在于另一个变量中

    我有一个数据框架 结构如下 a lt c 1 1 1 2 2 2 3 3 3 3 4 4 b lt c 1 2 3 1 2 3 1 2 3 4 1 2 c lt c NA NA 2 NA 1 1 NA NA 1 1 NA NA df lt
  • 从数据框中绘制多条平滑线

    我对 R 比较陌生 我正在尝试绘制从 csv 文件加载的数据框 数据由 6 列组成 如下所示 xval col1 col2 col3 col4 col5 第一列 xval 由一系列单调递增的正整数 例如 10 40 60 等 组成 其他列
  • 要在子集中显示的非数字条目的维恩图

    我有以下数据框 SET1 SET2 SET3 par1 par2 par1 par2 par3 par2 par3 par4 par5 我想制作一个维恩图 其中所有这些 parX 元素都显示在各自的子集中 即作为标签 而不仅仅是重叠元素的数
  • case_when 与部分字符串匹配和 contains()

    我正在使用一个数据集 其中有许多名为 status1 status2 等的列 在这些列中 它表示某人是否豁免 完整 注册等 不幸的是 豁免投入并不一致 这是一个示例 library dplyr problem lt tibble perso
  • 如何更改 aptana studio 的背景颜色?

    如何将 Aptana IDE 或整个主题 的黑色背景更改为其他背景 例如蓝色 正如 gyozo 在评论中提到的 对于蓝色主题 请使用 窗口 gt 首选项 gt Aptana Studio gt 主题 并选择 Eclipse 主题

随机推荐