Open mattijn opened 1 year ago
Very cool! I saw that there is an open PR on this in the Vega-Lite repo as well https://github.com/vega/vega-lite/pull/8601. I agree with you that a special function just for this does not seem to add that much, but we should definitely add an example to the gallery or main documentation to make it more discoverable.
A note here that if we add binding_color
, we should consider deprecating binding
similarly to what we did with selections in #2923
Not exactly sure since there are likely more options that could be explored using the binding
function, see: https://developer.mozilla.org/en-US/docs/Web/HTML/Element/input
You're right, there are many cool options to explore. I just discovered that it it possible to build a search box to filter/highlight the data directly in altair/vega-lite! I think we should add the color and search binding examples to the gallery, what do you think? Maybe even adding a section in the interactive page in the docs (although that page is becoming long now, maybe this could be a tutorial/showcase)
import altair as alt
from vega_datasets import data
search_box = alt.param(
value='',
bind=alt.binding(
input='search',
placeholder="Car model",
name='Search ',
)
)
alt.Chart(data.cars.url).mark_point(size=60).encode(
x='Horsepower:Q',
y='Miles_per_Gallon:Q',
tooltip='Name:N',
opacity=alt.condition(
alt.expr.test(alt.expr.regexp(search_box, 'i'), alt.datum.Name),
# alt.expr.indexof(alt.datum.Name, search_box) != -1, # this also works, but is not as powerful as regex
alt.value(0.8),
alt.value(0.1)
)
).add_params(
search_box
)
https://user-images.githubusercontent.com/4560057/226503462-4ff3df58-cbb4-41b9-bf0c-e12b09d122e1.mp4
You can also search for regexes, e.g. mazda|ford
. Inspiration from https://vega.github.io/vega/examples/job-voyager/ (it would be neat to also include an example of the "all" option in the altair docs, since it is not straightforward but useful)
Really nice. Yes. An example for this would be great. Maybe a new section named 'binding' and then an example per bind type?
Yeah, or maybe I can fit them into our current binding and expression sections... I might need to re-organize a bit, but that's ok since I am not sure the data-driven and logic-driven organization I suggested before really makes sense anyways. I'll see if I can try something in the next few days.
Hey @joelostblom, thank you for showcasing such a useful feature! Would you mind showing an example where one can do filtering instead of highlighting data, with a regex expression? I've been trying several things with no luck.
Instead of a condition for opacity highlighting you should include a filter transform.
import altair as alt
from vega_datasets import data
search_box = alt.param(
value='',
bind=alt.binding(
input='search',
placeholder="Car model",
name='Search ',
)
)
alt.Chart(data.cars.url).mark_point(size=60).encode(
x='Horsepower:Q',
y='Miles_per_Gallon:Q',
tooltip='Name:N',
).add_params(
search_box
).transform_filter(alt.expr.test(alt.expr.regexp(search_box, 'i'), alt.datum.Name))
Thank you for the answer @mattijn 🙌🏼 ! Do you know if it is possible to only update the graph when pressing enter, rather than as one types?
You would need to make use of an interactive JupyterChart object (docs). As such:
import altair as alt
from vega_datasets import data
import ipywidgets
# define a text and button widget
text = ipywidgets.Text(placeholder='enter a partial match to search', description='search')
button = ipywidgets.Button(description='click to search')
# define an altair parameter named SEARCH
param_search = alt.param(name='SEARCH')
# build altair chart
chart = alt.Chart(data.cars.url).mark_point(size=60).encode(
x='Horsepower:Q',
y='Miles_per_Gallon:Q',
tooltip='Name:N',
).add_params(
param_search
).transform_filter(alt.expr.test(alt.expr.regexp(param_search, 'i'), alt.datum.Name))
# create a JupyterChart object from the altair chart
jchart = alt.JupyterChart(chart)
# define a function to handle button click events
# on button click: update the SEARCH param using the input of the text widget
def on_button_clicked(b):
jchart.params.SEARCH = text.value
# register the function to the button
button.on_click(on_button_clicked)
# layout the text and button widget horizontally and the JupyerChart object below it
ipywidgets.VBox([
ipywidgets.HBox([text, button]),
jchart
])
I saw this tweet https://twitter.com/WoottonDylan/status/1603799316270718977?s=20&t=TA76W5lTMJvZmfPbEXfTMA.
This can be reproduced in altair with:
Would it be useful to have a
binding_color
utility around here https://github.com/altair-viz/altair/blob/master/altair/vegalite/v5/api.py#L431?I could not find a specific
core.BindColor
class, so it could be something as such:not sure if
binding_color(name='color rain')
is a true improvement overalt.binding(input='color', name='color rain')
though.