如何根据串扰条件动态更改绘图轴
how to dynamically change plotly axis based on crosstalk conditions
这个问题有been asked before,但是因为没有reprex所以没有得到答案,所以让我试一试。
假设我有两个跨越不同日期范围的数据集。我想使用滑块控制每个的可视化。以下 reprex 将直接在下方创建视觉效果。
---
title: "Untitled"
output: html_document
---
```{r setup, include=FALSE}
knitr::opts_chunk$set(echo = FALSE)
#+ message = FALSE, warning = FALSE
library(plotly)
library(crosstalk)
library(dplyr)
#+
```
```{r}
df1 <- data.frame(d = seq.Date(from = as.Date("2020-01-01"), by = "months", length.out = 100), v = runif(100))
df2 <- data.frame(d = seq.Date(from = as.Date("2020-6-01"), by = "months", length.out = 20), other_v = runif(20))
both_df <- full_join(df1, df2, by = 'd')
both_df_sh <- both_df %>% SharedData$new(group = "boom")
selector <- filter_slider(id = "selector1", label = "select dates", sharedData = both_df_sh, column = ~d)
v_p <- both_df_sh %>% plot_ly(x = ~d) %>% add_lines(y = ~v, name = "v", color = I("blue"))
other_v_p <- both_df_sh %>% plot_ly(x = ~d) %>% add_lines(y = ~other_v, name = "other v", color = I("red"))
```
```{r}
crosstalk::bscols(v_p, other_v_p)
```
这是正确的,因为两个图表都正确显示了它们的日期范围。但是,如果该范围内不存在数据,我的客户希望在图表中看到空白。像这样:
---
title: "Untitled"
output: html_document
---
```{r setup, include=FALSE}
knitr::opts_chunk$set(echo = FALSE)
#+ message = FALSE, warning = FALSE
library(plotly)
library(crosstalk)
library(dplyr)
#+
```
```{r}
df1 <- data.frame(d = seq.Date(from = as.Date("2020-01-01"), by = "months", length.out = 100), v = runif(100))
df2 <- data.frame(d = seq.Date(from = as.Date("2020-6-01"), by = "months", length.out = 20), other_v = runif(20))
both_df <- full_join(df1, df2, by = 'd')
both_df_sh <- both_df %>% SharedData$new(group = "boom")
selector <- filter_slider(id = "selector1", label = "select dates", sharedData = both_df_sh, column = ~d)
v_p <- both_df_sh %>% plot_ly(x = ~d) %>% add_lines(y = ~v, name = "v", color = I("blue")) %>%
layout(xaxis = list(range = list(min(both_df_sh$data()$d, na.rm = TRUE),
max(both_df_sh$data()$d, na.rm = TRUE))))
other_v_p <- both_df_sh %>% plot_ly(x = ~d) %>% add_lines(y = ~other_v, name = "other v", color = I("red")) %>%
layout(xaxis = list(range = list(min(both_df_sh$data()$d, na.rm = TRUE),
max(both_df_sh$data()$d, na.rm = TRUE))))
```
```{r}
selector
```
```{r}
crosstalk::bscols(v_p, other_v_p)
```
正如预期的那样,这给了我们这个:
这就是我想要的!然而,现在,图表不再随 filter_select
缩放,它仅隐藏数据,这不会创建可爱的视觉效果:
所以,我希望图表限制在拖动条形图时“掠过”...但要做到这一点,我当时需要 filter_select
的值。
我以为我可以通过像这样更改限制来预先获得它:
selector_values <- jsonlite::fromJSON(selector$children[[3]]$children[[1]])$values
v_p <- both_df_sh %>% plot_ly(x = ~d) %>% add_lines(y = ~v, name = "v", color = I("blue")) %>%
layout(xaxis = list(range = min(selector_values), max(selector_values)))
other_v_p <- both_df_sh %>% plot_ly(x = ~d) %>% add_lines(y = ~other_v, name = "other v", color = I("red")) %>%
layout(xaxis = list(range = min(selector_values), max(selector_values)))
但这些值在仪表板启动后不会重新评估。我需要一种方法来访问这些选择器的当前值...我该怎么做?
我们可以使用 plotly 的 matches
参数来对齐多个绘图的轴,就像我所做的那样 :
---
title: "Untitled"
output: html_document
---
```{r setup, include=FALSE}
knitr::opts_chunk$set(echo = FALSE)
#+ message = FALSE, warning = FALSE
library(plotly)
library(crosstalk)
library(dplyr)
#+
```
```{r}
df1 <- data.frame(d = seq.Date(from = as.Date("2020-01-01"), by = "months", length.out = 100), v = runif(100))
df2 <- data.frame(d = seq.Date(from = as.Date("2020-6-01"), by = "months", length.out = 20), other_v = runif(20))
both_df <- full_join(df1, df2, by = 'd')
both_df_sh <- both_df %>% SharedData$new(group = "boom")
selector <- filter_slider(id = "selector1", label = "select dates", sharedData = both_df_sh, column = ~d)
v_p <- both_df_sh %>% plot_ly(x = ~d) %>% add_lines(y = ~v, name = "v", color = I("blue"))
other_v_p <- both_df_sh %>% plot_ly(x = ~d) %>% add_lines(y = ~other_v, name = "other v", color = I("red")) %>% layout(xaxis = list(matches = "x"))
```
```{r}
selector
```
```{r, out.width='100%'}
subplot(v_p, other_v_p, shareX = TRUE, shareY = TRUE)
```
原回答:
我不确定我是否正确理解了您的预期输出,但如果您想自动缩放 x-axes,只需删除 xaxis range
(layout()
调用)。 crosstalk
将负责根据 filter_slider
:
提供过滤后的数据
---
title: "Untitled"
output: html_document
---
```{r setup, include=FALSE}
knitr::opts_chunk$set(echo = FALSE)
#+ message = FALSE, warning = FALSE
library(plotly)
library(crosstalk)
library(dplyr)
#+
```
```{r}
df1 <- data.frame(d = seq.Date(from = as.Date("2020-01-01"), by = "months", length.out = 100), v = runif(100))
df2 <- data.frame(d = seq.Date(from = as.Date("2020-6-01"), by = "months", length.out = 20), other_v = runif(20))
both_df <- full_join(df1, df2, by = 'd')
both_df_sh <- both_df %>% SharedData$new(group = "boom")
selector <- filter_slider(id = "selector1", label = "select dates", sharedData = both_df_sh, column = ~d)
v_p <- both_df_sh %>% plot_ly(x = ~d) %>% add_lines(y = ~v, name = "v", color = I("blue"))
other_v_p <- both_df_sh %>% plot_ly(x = ~d) %>% add_lines(y = ~other_v, name = "other v", color = I("red"))
```
```{r}
selector
```
```{r}
crosstalk::bscols(v_p, other_v_p)
```
non-crosstalk 方法,使用共享 x-axis 和范围滑块:
library(plotly)
library(dplyr)
df1 <- data.frame(d = seq.Date(from = as.Date("2020-01-01"), by = "months", length.out = 100), v = runif(100))
df2 <- data.frame(d = seq.Date(from = as.Date("2020-6-01"), by = "months", length.out = 20), other_v = runif(20))
both_df <- full_join(df1, df2, by = 'd')
fig1 <- plot_ly(both_df, x = ~ d, y = ~ v, type = "scatter", mode = "lines")
fig2 <- plot_ly(both_df, x = ~ d, y = ~ other_v, type = "scatter", mode = "lines")
fig_shared_x <- subplot(fig1, fig2, nrows = 2, shareX = TRUE)
fig_shared_x
fig_rangeslider <- fig_shared_x %>% layout(xaxis = list(rangeslider = list(type = "date")))
fig_rangeslider
这个问题有been asked before,但是因为没有reprex所以没有得到答案,所以让我试一试。
假设我有两个跨越不同日期范围的数据集。我想使用滑块控制每个的可视化。以下 reprex 将直接在下方创建视觉效果。
---
title: "Untitled"
output: html_document
---
```{r setup, include=FALSE}
knitr::opts_chunk$set(echo = FALSE)
#+ message = FALSE, warning = FALSE
library(plotly)
library(crosstalk)
library(dplyr)
#+
```
```{r}
df1 <- data.frame(d = seq.Date(from = as.Date("2020-01-01"), by = "months", length.out = 100), v = runif(100))
df2 <- data.frame(d = seq.Date(from = as.Date("2020-6-01"), by = "months", length.out = 20), other_v = runif(20))
both_df <- full_join(df1, df2, by = 'd')
both_df_sh <- both_df %>% SharedData$new(group = "boom")
selector <- filter_slider(id = "selector1", label = "select dates", sharedData = both_df_sh, column = ~d)
v_p <- both_df_sh %>% plot_ly(x = ~d) %>% add_lines(y = ~v, name = "v", color = I("blue"))
other_v_p <- both_df_sh %>% plot_ly(x = ~d) %>% add_lines(y = ~other_v, name = "other v", color = I("red"))
```
```{r}
crosstalk::bscols(v_p, other_v_p)
```
这是正确的,因为两个图表都正确显示了它们的日期范围。但是,如果该范围内不存在数据,我的客户希望在图表中看到空白。像这样:
---
title: "Untitled"
output: html_document
---
```{r setup, include=FALSE}
knitr::opts_chunk$set(echo = FALSE)
#+ message = FALSE, warning = FALSE
library(plotly)
library(crosstalk)
library(dplyr)
#+
```
```{r}
df1 <- data.frame(d = seq.Date(from = as.Date("2020-01-01"), by = "months", length.out = 100), v = runif(100))
df2 <- data.frame(d = seq.Date(from = as.Date("2020-6-01"), by = "months", length.out = 20), other_v = runif(20))
both_df <- full_join(df1, df2, by = 'd')
both_df_sh <- both_df %>% SharedData$new(group = "boom")
selector <- filter_slider(id = "selector1", label = "select dates", sharedData = both_df_sh, column = ~d)
v_p <- both_df_sh %>% plot_ly(x = ~d) %>% add_lines(y = ~v, name = "v", color = I("blue")) %>%
layout(xaxis = list(range = list(min(both_df_sh$data()$d, na.rm = TRUE),
max(both_df_sh$data()$d, na.rm = TRUE))))
other_v_p <- both_df_sh %>% plot_ly(x = ~d) %>% add_lines(y = ~other_v, name = "other v", color = I("red")) %>%
layout(xaxis = list(range = list(min(both_df_sh$data()$d, na.rm = TRUE),
max(both_df_sh$data()$d, na.rm = TRUE))))
```
```{r}
selector
```
```{r}
crosstalk::bscols(v_p, other_v_p)
```
正如预期的那样,这给了我们这个:
这就是我想要的!然而,现在,图表不再随 filter_select
缩放,它仅隐藏数据,这不会创建可爱的视觉效果:
所以,我希望图表限制在拖动条形图时“掠过”...但要做到这一点,我当时需要 filter_select
的值。
我以为我可以通过像这样更改限制来预先获得它:
selector_values <- jsonlite::fromJSON(selector$children[[3]]$children[[1]])$values
v_p <- both_df_sh %>% plot_ly(x = ~d) %>% add_lines(y = ~v, name = "v", color = I("blue")) %>%
layout(xaxis = list(range = min(selector_values), max(selector_values)))
other_v_p <- both_df_sh %>% plot_ly(x = ~d) %>% add_lines(y = ~other_v, name = "other v", color = I("red")) %>%
layout(xaxis = list(range = min(selector_values), max(selector_values)))
但这些值在仪表板启动后不会重新评估。我需要一种方法来访问这些选择器的当前值...我该怎么做?
我们可以使用 plotly 的 matches
参数来对齐多个绘图的轴,就像我所做的那样
---
title: "Untitled"
output: html_document
---
```{r setup, include=FALSE}
knitr::opts_chunk$set(echo = FALSE)
#+ message = FALSE, warning = FALSE
library(plotly)
library(crosstalk)
library(dplyr)
#+
```
```{r}
df1 <- data.frame(d = seq.Date(from = as.Date("2020-01-01"), by = "months", length.out = 100), v = runif(100))
df2 <- data.frame(d = seq.Date(from = as.Date("2020-6-01"), by = "months", length.out = 20), other_v = runif(20))
both_df <- full_join(df1, df2, by = 'd')
both_df_sh <- both_df %>% SharedData$new(group = "boom")
selector <- filter_slider(id = "selector1", label = "select dates", sharedData = both_df_sh, column = ~d)
v_p <- both_df_sh %>% plot_ly(x = ~d) %>% add_lines(y = ~v, name = "v", color = I("blue"))
other_v_p <- both_df_sh %>% plot_ly(x = ~d) %>% add_lines(y = ~other_v, name = "other v", color = I("red")) %>% layout(xaxis = list(matches = "x"))
```
```{r}
selector
```
```{r, out.width='100%'}
subplot(v_p, other_v_p, shareX = TRUE, shareY = TRUE)
```
原回答:
我不确定我是否正确理解了您的预期输出,但如果您想自动缩放 x-axes,只需删除 xaxis range
(layout()
调用)。 crosstalk
将负责根据 filter_slider
:
---
title: "Untitled"
output: html_document
---
```{r setup, include=FALSE}
knitr::opts_chunk$set(echo = FALSE)
#+ message = FALSE, warning = FALSE
library(plotly)
library(crosstalk)
library(dplyr)
#+
```
```{r}
df1 <- data.frame(d = seq.Date(from = as.Date("2020-01-01"), by = "months", length.out = 100), v = runif(100))
df2 <- data.frame(d = seq.Date(from = as.Date("2020-6-01"), by = "months", length.out = 20), other_v = runif(20))
both_df <- full_join(df1, df2, by = 'd')
both_df_sh <- both_df %>% SharedData$new(group = "boom")
selector <- filter_slider(id = "selector1", label = "select dates", sharedData = both_df_sh, column = ~d)
v_p <- both_df_sh %>% plot_ly(x = ~d) %>% add_lines(y = ~v, name = "v", color = I("blue"))
other_v_p <- both_df_sh %>% plot_ly(x = ~d) %>% add_lines(y = ~other_v, name = "other v", color = I("red"))
```
```{r}
selector
```
```{r}
crosstalk::bscols(v_p, other_v_p)
```
non-crosstalk 方法,使用共享 x-axis 和范围滑块:
library(plotly)
library(dplyr)
df1 <- data.frame(d = seq.Date(from = as.Date("2020-01-01"), by = "months", length.out = 100), v = runif(100))
df2 <- data.frame(d = seq.Date(from = as.Date("2020-6-01"), by = "months", length.out = 20), other_v = runif(20))
both_df <- full_join(df1, df2, by = 'd')
fig1 <- plot_ly(both_df, x = ~ d, y = ~ v, type = "scatter", mode = "lines")
fig2 <- plot_ly(both_df, x = ~ d, y = ~ other_v, type = "scatter", mode = "lines")
fig_shared_x <- subplot(fig1, fig2, nrows = 2, shareX = TRUE)
fig_shared_x
fig_rangeslider <- fig_shared_x %>% layout(xaxis = list(rangeslider = list(type = "date")))
fig_rangeslider