Search code examples
rggplot2plotlyr-markdowndt

Dynamic filter crosstalk-linked plotly based on DT search


I have data that combines text and scores. I would like to render an HTML file with client-side dynamic text search connected to a plotly scatter plot.

Currently, clicking on one or more point(s) in the plot will display the relevant row(s) in the DT. But going the other way, by selecting rows or searching for phrases in the DT table, does not change the highlighted points in the plot. Ideally, if we search for a phrase (e.g. "Obama") in the DT table, the related points would immediately be highlighted. Is there some way to do that?

Alternatively, should I use filter_select from crosstalk or a plotly option to make it possible to filter points based on the appearance of target text in the sentence field?

---
title: "Untitled"
output: html_document
---

```{r }
library(tidyverse)
library(crosstalk)
library(plotly)
set.seed(0)
n = 20
survey <- data.frame(id = 1:n,
                     date = as.Date("2023-01-01") + runif(n = n, max = 100),
                     score = sample(0:10, n, replace = TRUE),
                     sentence = wakefield::sentence(n = n) |> str_wrap(40))

survey_shared <- SharedData$new(survey, key = ~id)

p <- ggplot(survey_shared, aes(date, score, text = sentence)) +
  geom_point()

ggplotly(p, tooltip = "text") %>% layout(hoverlabel = list(align = "left")) 

DT::datatable(survey_shared, rownames = FALSE, width = "100%")

```

enter image description here


Solution

  • I'm not (yet) sure why, but it works once you remove the key from your SharedData$new call (row.names are used by default).

    Edit: datatable seems to expect a character key. Using id = as.character(1:n) when defining the data.frame makes your initial code functional.

    ---
    title: "Untitled"
    output: html_document
    ---
    
    ```{r }
    library(tidyverse)
    library(crosstalk)
    library(plotly)
    library(DT)
    
    set.seed(0)
    n = 20
    survey <- data.frame(id = 1:n,
                         date = as.Date("2023-01-01") + runif(n = n, max = 100),
                         score = sample(0:10, n, replace = TRUE),
                         sentence = wakefield::sentence(n = n) |> str_wrap(40))
    
    survey_shared <- SharedData$new(survey)
    
    p <- ggplot(survey_shared, aes(date, score, text = sentence)) +
      geom_point()
    
    ggplotly(p, tooltip = "text") %>% layout(hoverlabel = list(align = "left")) %>% highlight(on = "plotly_click", off = "plotly_doubleclick") %>% highlight(on = "plotly_selected", off = "plotly_deselect") # for lasso and box select
    DT::datatable(survey_shared, rownames = FALSE, width = "100%")
    
    ```