How to Dynamically Change Plotly Axis Based on Crosstalk Conditions

how to dynamically change plotly axis based on crosstalk conditions

We can use plotly's matches parameter to align the axes of multiple plots just as I did here:

---
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)
```

result


Original answer:

I'm not sure if I understand your expected output correctly but if you want to autoscale the x-axes just remove the xaxis range (the layout() call). crosstalk will take care about providing the filtered data based on the 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)
```

result

A non-crosstalk approach, using a shared x-axis and a rangeslider:

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

result

Crosstalk: Change Plotly Graph on Startup

A smoother workaround is to use the window.onload hook. This avoids the need to specify the timeout delay and as opposed to $.ready fires not once the DOM is loaded, but the whole page is ready. Exactly what I need, unless there is a dedicated hook in plotly for this kind of operation? plotly_afterplot semmed to be the right candidate. Yet again this is not available on $.ready

window.onload = function() {
// set dropdown to first element
$('.selectized').each(function(idx, el) {
const sel = this.selectize;
const options = Object.keys(sel.options);
sel.setValue(options[0]);
});

Managing multiple Times Series with Crosstalk and plotly

Are you looking for something like that instead:

plot_ly() %>%
add_lines(data = df_1, x= ~date, y = ~psavert, name = "First") %>%
add_lines(data = df_2, x= ~date, y = ~psavert, name = "Second") %>%
layout(
updatemenus = list(
list(
y = 0.8,
type= 'buttons',
buttons = list(
list(method = "restyle",
args = list("visible", list(TRUE, TRUE)),
label = "Both"),
list(method = "restyle",
args = list("visible", list(TRUE, FALSE)),
label = "First"),

list(method = "restyle",
args = list("visible", list(FALSE, TRUE)),
label = "Second")))
)
)

Plotly: shareX between side-by-side plots

We can use matches in R just as we can in python.

Run schema() and navigate:

object ► layout ► layoutAttributes ► xaxis ► matches

for more info.

This keeps all (x&y) axes synced:

library(plotly) 

n = 10
x = 1:n
y = rnorm(n)

fig1 <- plot_ly(x = x, y = y, type = 'scatter', mode = 'lines+markers')
fig2 <- plot_ly(x = x, y = y, type = 'scatter', mode = 'lines+markers', xaxis = "x") %>% layout(xaxis = list(matches = "x"))
fig <- subplot(fig1, fig2, shareX = TRUE, shareY = TRUE)
fig

result



Related Topics



Leave a reply



Submit