Create Selection For Filter Based On Interactive Ggplot Using Javascript
Solution 1:
What about something like this? This is from Interactive web-based data visualization with R, plotly, and shiny by Carson Sievert Published by CRC press
---title:"Untitled"author:"Daniel"date:"4/7/2021"output:html_document---
```{rsetup,include=FALSE}knitr::opts_chunk$set(echo=TRUE)``````{r}library(ggplot2)library(plotly)library(DT)m<-highlight_key(mpg)p<-ggplot(m,aes(displ,hwy))+geom_point(aes(color=cyl))+geom_smooth(se=TRUE)gg<-highlight(ggplotly(p),"plotly_selected")m<-highlight_key(mpg)p<-ggplot(m,aes(displ,hwy))+geom_point(aes(color=cyl))+geom_smooth(se=TRUE)gg<-highlight(ggplotly(p),"plotly_selected")crosstalk::bscols(gg,DT::datatable(m))```
Where you get a crosstalk DT in plotly
Solution 2:
Here's a slightly more useful take on the problem:
---
output:
html_document
---
```{r setup, include=FALSE}
library(ggplot2)
library(ggiraph)
knitr::opts_chunk$set(echo = TRUE)
library(knitr)
library(crosstalk)
library(reactable)
library(tibble)
```
```{r, echo = FALSE, message = FALSE}
dat <- tibble::tribble(~value, ~x, ~y,
"A", 1, 1,
"B", 2, 1,
"A", 1, 2,
"B", 2, 2,
"A", 1, 3,
"B", 2, 3,
"A", 1, 2,
"B", 2, 3)
shared_dat <- SharedData$new( dat, group="abSelector" )
# Rectangle A
group_A <- data.frame(x1 = 0,
x2 = 3,
y1 = 0,
y2 = 1,
r = "A")
# Polygon B
group_B <- data.frame(x = c(3,4,4,0,0,3),
y = c(0,0,2,2,1,1),
r = "B")
p <- ggplot() +
geom_rect_interactive(data = group_A,
aes(xmin = x1, xmax = x2, ymin = y1,
ymax = y2, data_id = r,
onclick = paste0("filterOn(\"",r,"\")")
),
alpha = .1, color = "black") +
geom_polygon_interactive(data = group_B,
aes(x = x, y = y, data_id = r,
onclick = paste0("filterOn(\"",r,"\")")
),
alpha = .1, color = "black") +
annotate("text", x = 0.1, y = .82,
label = "A",
fontface = 2, hjust = 0) +
annotate("text", x = 0.1, y = 1.82,
label = "B",
fontface = 2, hjust = 0) +
theme_void()
g <- girafe(ggobj = p)
rt <- reactable(
shared_dat,
elementId = "ABtable"
)
fs <- filter_select("letterFilter", "Filter", shared_dat, group=~value, multiple=FALSE )
bscols(
list( fs, rt ),
g
)
```
<script>
$(function() {
// Necessary to trigger selectize initialization
$("#letterFilter input").focus();
setTimeout( function(){ $("#letterFilter input").blur(); }, 0);
});
filterOn = function(letter) {
var obj = $("#letterFilter div[data-value='" + letter + "']");
obj.click();
}
</script>
As you will see, there are three components to it:
- a filter_select
- a reactable
- your plot
Behind the scenes there's the SharedData object encapsulating your data and that know's how its being filtered.
Now ideally I'd use a crosstalk.FilterHandle
to control the filtering, but it doesn't seem to play well with filter_select
. I'd rather updat the selectize value and have the filtering happen based onthat, where as the FilterHandle filters the data directly, bypassing the actual filter string and instead dictating which elements to show. Which would have made for a more clunky solution in which I do the filtering myself, update shown elements, and then update the actual search key shown.
As it is now, I just fire a .click()
on the filter option corresponding to the letter in the plot (using jQuery). I also have to focus and blur upon loading the document to trigger building of the filter options, which you will see in the code above.
Post a Comment for "Create Selection For Filter Based On Interactive Ggplot Using Javascript"