Shiny 反应式
概述
之前我们描述了如何使用 ojs_define()
函数将 Python 和 R 中的数据提供给 OJS 单元格使用。在这种情况下,数据预处理在渲染时只进行一次,随后的所有交互都在客户端处理。
但是如果你想根据用户输入动态地进行数据转换呢?这也是可能的,因为 ojs_define()
不仅可以传递静态值,还可以传递 Shiny 反应式(假设它在 Shiny 交互文档 中运行)。
你好,Shiny
以下是 Shiny Gallery 中的 K-Means 聚类 示例,通过 OJS 客户端和 Shiny 服务器实现:
你可以在 https://jjallaire.shinyapps.io/kmeans-shiny-ojs/ 查看部署的文档。
源代码
我们来看一下源代码。在客户端,我们有看起来熟悉的 OJS 输入和一个使用 panel: sidebar
和 panel: fill
布局的图表:
```{ojs}
//| panel: sidebar
vars = ["Sepal.Length", "Sepal.Width", "Petal.Length", "Petal.Width"]
viewof xcol = Inputs.select(vars, {label: "X 变量"})
viewof ycol = Inputs.select(vars, {label: "Y 变量", value: vars[1]})
viewof count = Inputs.range([1, 9], {label: "聚类数量", step: 1, value: 3})
```
```{ojs}
//| panel: fill
Plot.plot({
color: {
type: "ordinal",
scheme: "category10"
},
marks: [
Plot.dot(transpose(selectedData), {
x: xcol,
y: ycol,
fill: (d, i) => clusters.cluster[i],
}),
Plot.dot(clusters.centers, {
x: d => d[0],
y: d => d[1],
r: 10,
stroke: "black",
fill: (d, i) => i + 1
}),
]
})
```
注意绘图代码引用了变量 selectedData
和 clusters
。这些将由 Shiny 服务器代码中的反应式表达式提供。还要注意我们使用 transpose()
函数将数据重塑为 Plot 库预期的行格式。
以下是服务器代码:
```{r}
#| context: server
selectedData <- reactive({
iris[, c(input$xcol, input$ycol)]
})
clusters <- reactive({
kmeans(selectedData(), input$count)
})
ojs_define(selectedData, clusters)
```
我们通过 context: server
选项指定这段代码在服务器上运行。
注意我们引用了客户端通过 viewof
表达式定义的几个输入(例如 input$xcol
)。当这些输入改变时,它们将导致服务器端相应的反应式重新执行。
我们创建了两个反应式值(selectedData
和 clusters
),并使用 ojs_define()
将它们提供给客户端。当这些值改变时,图表将自动在客户端重新绘制。
示例
以下是一些展示了使用 OJS 与 Shiny 的各种方式的示例:
示例 | 源代码 | 描述 |
---|---|---|
K-Means | 代码 | 简单示例,展示如何将 OJS 输入绑定到 Shiny 输入,并将 Shiny 反应式绑定到 OJS 图表。 |
Binning | 代码 | 演示在服务器上对中等大小数据集(32mb)进行快速分箱。 |
数据绑定 | 代码 | 演示如何从 https://observablehq.com 导入笔记本,并将其数据字段绑定到 Shiny 反应式。 |
绑定
OJS 到 Shiny
在上面的示例中,我们利用了默认情况下 OJS viewof
表达式会自动传播到 Shiny 输入(例如 input$xcol
)的事实。这提供了合理的关注点分离,并防止在具有大型 OJS 变量的情况下产生过多的网络流量。
然而,如果你想使用其他 OJS 变量作为 Shiny 输入,这也是可能的,使用 ojs-export
选项即可。默认行为映射到以下配置:
---
server:
type: shiny
ojs-export: viewof
---
你也可以指定 ojs-export: all
以使所有 OJS 反应式绑定到 Shiny 输入:
---
server:
type: shiny
ojs-export: all
---
或者,你可以通过名称指定一个OJS反应列表(包括使用~
来过滤出反应),并可选择将其与viewof
和/或all
选项结合使用。例如:
---
server:
type: shiny
ojs-export: [all, ~large_dataset]
---
Shiny到OJS
不太常见但偶尔有用的是将Shiny输入绑定到OJS的能力。默认情况下不会发生此类绑定,但你可以使用ojs-import
选项选择特定的Shiny输入。例如:
---
server:
type: shiny
ojs-import: [minimum, maximum]
---