Shiny从入门到入定——11-书签
发表于:2024-04-27 | 分类: IT
字数统计: 2.4k | 阅读时长: 9分钟 | 阅读量:

11 书签

与大多数网站相比,Shiny应用程序有一个主要的缺点:您无法为应用程序添加书签以便将来返回同一位置,也无法通过电子邮件中的链接与他人分享您的工作。这是因为,默认情况下,Shiny不会在URL中公开应用程序的当前状态。然而,幸运的是,通过一些额外的工作,您可以更改此行为,本章将向您展示如何操作。

1
library(shiny)

11.1 基本思路

让我们用一个简单的应用程序来演示如何使其具有书签功能。这个应用程序绘制了利萨茹曲线,这些曲线复制了摆锤的运动。这个应用程序可以生成各种有趣的图案,您可能想要与他人分享。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
ui <- fluidPage(
sidebarLayout(
sidebarPanel(
sliderInput("omega", "omega", value = 1, min = -2, max = 2, step = 0.01),
sliderInput("delta", "delta", value = 1, min = 0, max = 2, step = 0.01),
sliderInput("damping", "damping", value = 1, min = 0.9, max = 1, step = 0.001),
numericInput("length", "length", value = 100)
),
mainPanel(
plotOutput("fig")
)
)
)
server <- function(input, output, session) {
t <- reactive(seq(0, input$length, length.out = input$length * 100))
x <- reactive(sin(input$omega * t() + input$delta) * input$damping ^ t())
y <- reactive(sin(t()) * input$damping ^ t())

output$fig <- renderPlot({
plot(x(), y(), axes = FALSE, xlab = "", ylab = "", type = "l", lwd = 2)
}, res = 96)
}

图11.1 这个应用程序允许您使用摆锤模型生成有趣的图案。如果能和朋友分享一个链接,岂不是很酷?

为了使这个应用程序具有书签功能,我们需要做三件事情:

  1. 在用户界面中添加一个bookmarkButton()。这将生成一个按钮,用户点击后生成可书签的URL。

  2. 将ui变为一个函数。您需要这样做是因为书签化的应用程序必须重新播放书签化的值:实际上,Shiny会修改每个输入控件的默认value。这意味着不再有一个单一的静态用户界面,而是可能有多个依赖于URL中参数的用户界面,因此它必须是一个函数。

  3. shinyApp()调用中添加enableBookmarking = "url"

进行这些更改后,我们得到:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
ui <- function(request) {
fluidPage(
sidebarLayout(
sidebarPanel(
sliderInput("omega", "omega", value = 1, min = -2, max = 2, step = 0.01),
sliderInput("delta", "delta", value = 1, min = 0, max = 2, step = 0.01),
sliderInput("damping", "damping", value = 1, min = 0.9, max = 1, step = 0.001),
numericInput("length", "length", value = 100),
bookmarkButton()
),
mainPanel(
plotOutput("fig")
)
)
)
}
1
shinyApp(ui, server, enableBookmarking = "url")

您可以在https://hadley.shinyapps.io/ms-bookmark-url尝试一下。如果您在应用程序中操作并书签了一些有趣的状态,您会发现生成的URL看起来像这样:

为了理解发生了什么,让我们以第一个URL为例,将其分解成几个部分:

  • http:// 是与应用程序通信时使用的“协议”。这始终是httphttps

  • hadley.shinyapps.io/ms-bookmark-url 是应用程序的位置。

问号?之后的所有内容都是“参数”。每个参数之间用&分隔,如果将其分解,您可以看到应用程序中每个输入的值:

  • damping=1

  • delta=1

  • length=100

  • omega=1

因此,“生成书签”意味着在URL的参数中记录输入的当前值。如果您在本地进行操作,URL看起来会略有不同:

除了将hadley.shinyapps.io/ms-bookmark-url替换为类似127.0.0.1:4087的内容外,大多数部分都是相同的。127.0.0.1是一个特殊地址,始终指向您自己的计算机,而4087是一个随机分配的端口。通常,不同的应用程序会获得不同的路径或IP地址,但如果您在自己的计算机上托管多个应用程序,则无法做到这一点。

11.1.1 更新URL

除了提供一个明确的按钮外,另一种选择是自动更新浏览器中的URL。这允许用户在其浏览器中使用用户书签命令,或者从地址栏复制和粘贴URL。

自动更新URL需要在服务器函数中编写一些模板代码:

1
2
3
4
5
6
7
# Automatically bookmark every time an input changes
observe({
reactiveValuesToList(input)
session$doBookmark()
})
# Update the query string
onBookmarked(updateQueryString)

这给我们提供了一个更新后的服务器函数,如下所示:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
server <- function(input, output, session) {
t <- reactive(seq(0, input$length, length = input$length * 100))
x <- reactive(sin(input$omega * t() + input$delta) * input$damping ^ t())
y <- reactive(sin(t()) * input$damping ^ t())

output$fig <- renderPlot({
plot(x(), y(), axes = FALSE, xlab = "", ylab = "", type = "l", lwd = 2)
}, res = 96)

observe({
reactiveValuesToList(input)
session$doBookmark()
})
onBookmarked(updateQueryString)
}
1
shinyApp(ui, server, enableBookmarking = "url")

这会产生https://hadley.shinyapps.io/ms-bookmark-auto——由于URL现在会自动更新,您可以从用户界面中删除书签按钮。

11.1.2 存储更丰富的状态

到目前为止,我们使用了enableBookmarking = "url",它直接在URL中存储状态。这是一个很好的起点,因为它非常简单,可以在您可能部署Shiny应用的任何地方工作。然而,可以想象,如果您有大量的输入,URL会变得非常长,而且显然无法捕获上传的文件。

对于这些情况,您可能想要使用enableBookmarking = "server",它将状态保存到服务器上的.rds文件。这总是生成一个简短的、不透明的URL,但需要在服务器上额外存储。

1
shinyApp(ui, server, enableBookmarking = "server")

目前,shinyapps.io尚不支持服务器端书签,因此您需要在本地尝试。如果您这样做,您会看到书签按钮生成类似以下的URL:

这些URL与您工作目录中匹配的目录配对:

  • shiny_bookmarks/0d645f1b28f05c97

  • shiny_bookmarks/87b56383d8a1062c

  • shiny_bookmarks/c8b0291ba622b69c

服务器端书签的主要缺点是它需要在服务器上保存文件,而且不清楚这些文件需要保留多长时间。如果您正在书签化复杂的状态并且从未删除这些文件,那么随着时间的推移,您的应用将占用越来越多的磁盘空间。如果您删除文件,一些旧书签将停止工作。

11.2 书签挑战

自动书签功能依赖于响应式图表。它使用保存的值初始化输入,然后重新播放所有的响应式表达式和输出,只要您的应用的响应式图表简单明了,就会产生与您看到的相同的应用。本节简要介绍了一些需要特别注意的情况:

  • 如果您的应用使用了随机数,即使所有输入都相同,结果也可能不同。如果确保每次生成相同的数字非常重要,您需要思考如何使随机过程可重复。最简单的方法是使用repeatable()函数;有关更多详细信息,请参阅相关文档。

  • 如果您有选项卡,并希望书签和恢复活动选项卡,请确保在调用tabsetPanel()时提供一个id。

  • 如果有不应被书签记录的输入,例如它们包含不应共享的个人信息,请在服务器函数的某个位置调用setBookmarkExclude()。例如,setBookmarkExclude(c("secret1", "secret2"))将确保secret1secret2输入不会被书签记录。

  • 如果您在自己的reactiveValues()对象中手动管理响应式状态(我们将在第16章中讨论),则需要使用onBookmark()onRestore()回调来手动保存和加载额外的状态。有关更多详细信息,请参阅高级书签

11.3 练习

  1. ambient::noise_simplex()的结果生成可视化应用。您的应用应允许用户控制频率、分形、间隙和增益,并且应支持书签功能。如何确保从书签重新加载时图像看起来完全相同?(考虑seed参数的含义)。

  2. 创建一个简单的应用,允许您上传CSV文件,并为其添加书签。上传几个文件,然后查看shiny_bookmarks。这些文件是如何与书签对应的?(提示:您可以使用readRDS()来查看Shiny生成的缓存文件的内容)。

11.4 总结

本章介绍了如何为您的应用程序启用书签功能。书签功能对您的用户来说是一个很好的特性,因为它允许他们轻松地将自己的工作与他人分享。接下来,我们将讨论如何在Shiny应用程序中使用整洁评估。整洁评估是许多tidyverse函数的一个特性,如果您希望允许用户在(例如)dplyr管道或ggplot2图形中更改变量,那么您需要了解这个特性。

加关注

生信之巅微信公众号 生信之巅小程序码

敬告:使用文中脚本请引用本文网址,请尊重本人的劳动成果,谢谢!Notice: When you use the scripts in this article, please cite the link of this webpage. Thank you!

上一篇:
Shiny从入门到入定——12-Tidy evaluation
下一篇:
Shiny从入门到入定——10-动态UI