如何从经crosstalk::filter_select过滤的SharedData对象中获取列?
问题
无法通过crosstalk::filter_select筛选SharedData对象后提取到筛选后的列,代码能运行但不响应筛选操作,怀疑shared_data$data(withFilter = TRUE)返回的是原始数据框而非筛选后的版本,如何获取筛选后的数据集?
附上的代码:
--- title: "Dull dashboard" output: flexdashboard::flex_dashboard: orientation: columns vertical_layout: fill --- ```{r echo=FALSE, message=FALSE, warning=FALSE} library(plotly) library(crosstalk) library(knitr) library(tidyverse) make_plot <- function(tbbl, label){ ggplot(tbbl, aes(wt, mpg, label=label))+ geom_text() } nested <- mtcars |> group_by(cyl) |> nest() |> mutate(plot=map2(data, cyl, make_plot)) |> select(-data) shared_data <- SharedData$new(nested)
Inputs {.sidebar data-width=250}
crosstalk::filter_select( "fltr", " Select # of cylinders", shared_data, ~cyl, multiple = FALSE, selected = "6" )
Column {data-width=700}
Plot
filtered_data <- shared_data$data(withFilter = TRUE) plt <- filtered_data$plot[[1]] ggplotly(plt)
## 原因分析 `crosstalk`的筛选是**客户端(浏览器端)**的交互操作,而`shared_data$data(withFilter = TRUE)`是在**R页面渲染阶段(服务器端)**执行的,此时还没有用户的筛选操作,因此始终返回原始数据框,无法响应后续的客户端筛选。 ## 解决方案 要让图表响应`crosstalk`的筛选,需要让可视化组件直接绑定`SharedData`,而非在R中提取筛选后的数据。以下是两种可行方案: ### 方案1:直接用SharedData驱动plotly图表(推荐) 取消预先生成嵌套plot的逻辑,让plotly直接基于`SharedData`绘制,筛选操作会自动触发客户端图表更新: ```r --- title: "Dull dashboard" output: flexdashboard::flex_dashboard: orientation: columns vertical_layout: fill --- ```{r echo=FALSE, message=FALSE, warning=FALSE} library(plotly) library(crosstalk) library(knitr) library(tidyverse) # 基于原始mtcars创建SharedData,指定cyl为关联键 shared_data <- SharedData$new(mtcars, key = ~cyl)
Inputs {.sidebar data-width=250}
crosstalk::filter_select( "fltr", "Select # of cylinders", shared_data, ~cyl, multiple = FALSE, selected = 6 )
Column {data-width=700}
Plot
# 直接用SharedData绘制图表,自动响应筛选 ggplot(shared_data, aes(wt, mpg, label = cyl)) + geom_text() |> ggplotly()
### 方案2:结合Shiny反应式逻辑(保留预生成plot的需求) 如果需要保留预先按cyl分组生成plot的逻辑,可以将flexdashboard切换为Shiny运行时,用Shiny的反应式机制响应筛选: ```r --- title: "Dull dashboard" output: flexdashboard::flex_dashboard: orientation: columns vertical_layout: fill runtime: shiny # 启用Shiny运行时 --- ```{r echo=FALSE, message=FALSE, warning=FALSE} library(plotly) library(crosstalk) library(knitr) library(tidyverse) make_plot <- function(tbbl, label){ ggplot(tbbl, aes(wt, mpg, label=label))+ geom_text() } nested <- mtcars |> group_by(cyl) |> nest() |> mutate(plot=map2(data, cyl, make_plot)) |> select(-data)
Inputs {.sidebar data-width=250}
# 用Shiny的selectInput替代crosstalk的filter_select selectInput("fltr", "Select # of cylinders", choices = unique(nested$cyl), selected = 6)
Column {data-width=700}
Plot
# 用renderPlotly创建反应式图表 renderPlotly({ filtered_data <- nested |> filter(cyl == input$fltr) plt <- filtered_data$plot[[1]] ggplotly(plt) })
--- 内容的提问来源于stack exchange,提问作者Richard Martin
相关产品推荐
相关产品推荐

