Reputation: 758
I have two pandas dataframes data
and data_queue
with the same structure containing similar data.
The former shall be plotted as a line while the latter as a scatter plot.
I need a shared selector to filter on both charts.
In the example below, the selector works only if I remove scatter
.
How to achieve that in Altair?
Note: I need the last layer
to add tooltip, rules, text, etc. to the line plot. For sake of readability, I omitted that part here.
input_dropdown = alt.binding_select(options=data.koplus_name.unique().tolist())
selection = alt.selection_single(fields=['koplus_name'], bind=input_dropdown, name='Koplus', init={'koplus_name': input_dropdown.options[0]})
line = alt.Chart(data).mark_line().encode(
x=alt.X('yearmonthdatehoursminutes(timestamp)', title='timestamp', scale=alt.Scale(domain=(str(data.timestamp.min()), str(data.timestamp.min() + pd.Timedelta(value=1, unit='D'))))),
y=alt.Y('value', axis=alt.Axis(title=''), scale=alt.Scale(domain=(0, data.value.max()))),
color=alt.Color('variable', legend=alt.Legend(title=None)),
)
scatter = alt.Chart(data_queue).mark_point().encode(
x='green time',
y='value',
)
chart = line + scatter
layer = alt.layer(
chart
).add_selection(
selection
).transform_filter(
selection
).properties(
width=800, height=250
).interactive(bind_y=False)
Upvotes: 1
Views: 1528
Reputation: 86310
If you want data to respond to the same selection, it has to be part of the same data source. You can either join the datasets in pandas before creating the chart, or join the datasets with a Lookup Transform within the Altair grammar.
Here is an example of the second approach, with some small datasets:
import numpy as np
import pandas as pd
import altair as alt
df1 = pd.DataFrame({
'x': np.arange(100),
'y': np.random.randn(100).cumsum()
})
df2 = pd.DataFrame({
'x': np.arange(100),
'z': np.random.randn(100).cumsum()
})
selection = alt.selection_interval(encodings=['x'])
base = alt.Chart(df1).transform_lookup(
lookup='x',
from_=alt.LookupData(data=df2, key='x', fields=['z'])
).mark_point(color='steelblue').encode(
x='x:Q',
color=alt.condition(selection, alt.value('steelblue'), alt.value('lightgray'))
)
alt.layer(
base.encode(y='y:Q'),
base.encode(y='z:Q')
).add_selection(
selection
)
Upvotes: 3