Open dbk123 opened 5 years ago
Yes, but you'll need to learn a bit about binding selections
When you do a chart like this:
import altair as alt
from vega_datasets import data
cars = data.cars()
alt.Chart(cars).mark_point().encode(
x='Horsepower',
y='Miles_per_Gallon',
color='Origin'
).interactive()
The interactive()
method is a shorthand for this:
alt.Chart(cars).mark_point().encode(
x='Horsepower',
y='Miles_per_Gallon'
color='Origin'
).add_selection(
alt.selection_interval(bind='scales')
)
Each time you call interactive()
, it will create a new (and independent) selection with a binding to scales. If you would like two panels in a chart to share the same selection binding, then you can specify it manually and attach the same selection object to each chart, for example:
resize = alt.selection_interval(bind='scales')
chart1 = alt.Chart(cars).mark_point().encode(
x='Horsepower',
y='Miles_per_Gallon',
color='Origin'
).add_selection(
resize
)
chart2 = alt.Chart(cars).mark_point().encode(
x='Horsepower',
y='Acceleration',
color='Origin'
).add_selection(
resize
)
alt.concat(chart1, chart2)
Because the selection is attached to both charts, changing it will change the scales of both charts.
Jake,
Thank you for the prompt and detailed feedback!!!!
-Dave
I'm going to reopen this as a reminder to myself to add this info to the docs.
Got it - sorry. (That will be very helpful thing to include!)
Is it possible to have this work with layered charts as well?
Essentially I have:
backgroundChartOne = alt.Chart(df)...
foregroundChartOne = alt.Chart(df)...
backgroundChartTwo = alt.Chart(df)...
foregroundChartTwo = alt.Chart(df)...
chartOne = backgroundChartOne + foregroundChartOne
chartTwo = backgroundChartTwo + foregroundChartTwo
chartOne | chartTwo
I would like to have an interactive x-axis that is linked between chartOne and chartTwo. However, I haven't been able to get this to work yet, I keep getting a Duplicate signal name: "selector067_tuple"
error.
I have tried, for example:
backgroundChartOne = alt.Chart(df)...
foregroundChartOne = alt.Chart(df)...
backgroundChartTwo = alt.Chart(df)...
foregroundChartTwo = alt.Chart(df)...
resize = alt.selection_interval(bind='scales')
backgroundChartOne = backgroundChartOne.add_selection(resize)
foregroundChartOne = foregroundChartOne.add_selection(resize)
backgroundChartTwo = backgroundChartTwo.add_selection(resize)
foregroundChartTwo = foregroundChartTwo.add_selection(resize)
chartOne = backgroundChartOne + foregroundChartOne
chartTwo = backgroundChartTwo + foregroundChartTwo
chartOne | chartTwo
and
backgroundChartOne = alt.Chart(df)...
foregroundChartOne = alt.Chart(df)...
backgroundChartTwo = alt.Chart(df)...
foregroundChartTwo = alt.Chart(df)...
resize = alt.selection_interval(bind='scales')
chartOne = backgroundChartOne + foregroundChartOne
chartTwo = backgroundChartTwo + foregroundChartTwo
chartOne = chartOne.add_selection(resize)
chartTwo = chartTwo.add_selection(resize)
chartOne | chartTwo
and neither of them seem to work.
You cannot bind the same selection object to two charts in a layer (this leads to duplicate signal names). Try binding the selection to only one of the subcharts in each layer.
For example, like this:
import altair as alt
import pandas as pd
df = pd.DataFrame({
'x': range(5),
'y': [1, 3, 2, 4, 0]
})
zoom = alt.selection_interval(bind='scales')
layer1 = alt.Chart(df).mark_line().encode(x='x', y='y').add_selection(zoom)
layer2 = alt.Chart(df).mark_point().encode(x='x', y='y')
chartOne = layer1 + layer2
Perfect, thank you so much!
Yes, but you'll need to learn a bit about binding selections
When you do a chart like this:
import altair as alt from vega_datasets import data cars = data.cars() alt.Chart(cars).mark_point().encode( x='Horsepower', y='Miles_per_Gallon', color='Origin' ).interactive()
The
interactive()
method is a shorthand for this:alt.Chart(cars).mark_point().encode( x='Horsepower', y='Miles_per_Gallon' color='Origin' ).add_selection( alt.selection_interval(bind='scales') )
Each time you call
interactive()
, it will create a new (and independent) selection with a binding to scales. If you would like two panels in a chart to share the same selection binding, then you can specify it manually and attach the same selection object to each chart, for example:resize = alt.selection_interval(bind='scales') chart1 = alt.Chart(cars).mark_point().encode( x='Horsepower', y='Miles_per_Gallon', color='Origin' ).add_selection( resize ) chart2 = alt.Chart(cars).mark_point().encode( x='Horsepower', y='Acceleration', color='Origin' ).add_selection( resize ) alt.concat(chart1, chart2)
Because the selection is attached to both charts, changing it will change the scales of both charts.
@jakevdp - is it possible to link both x and y axes so they are both synchronized on zooming?
Yes, the last code snippet you quoted should do this.
zoom = alt.selection_interval(bind='scales')
selector = alt.selection_single(
empty='all',
fields=['ticker']
)
base = alt.Chart(df).transform_filter(
# slider_selection
(alt.datum.date2 >= select_range_start.date) & (
alt.datum.date2 <= select_range_end.date)
).add_selection(
selector,
select_range_start,
select_range_end
)
bars = base.mark_bar().encode(
# https://stackoverflow.com/questions/52877697/order-bar-chart-in-altair
x=alt.X('ticker',
sort=alt.EncodingSortField(
field="ticker", op="count", order='descending'),
axis=alt.Axis(title='Stock Tickers')
),
y=alt.Y("count(id)",
axis=alt.Axis(title='Number of Mentions'),
# scale=alt.Scale(zero=False)
),
color=alt.condition(selector, 'id:O', alt.value(
'lightgray'), legend=None),
).properties(
width=1400,
height=600
).add_selection(
zoom
)
The x axis is just stock tickers. they y axis is count. I want to zoom in the bars that are really small. ie - the bars would get taller as I zoom-in on just the y-axis Is this even supported? seems like zoom only works if both x and y axis are not string.
EDIT: used a slider, selection_single, transform_aggregate, and transform_filter to achieve what I wanted
Vega-lite currently does not support selections on aggregated fields; see https://github.com/vega/vega-lite/issues/5308. You're using a count
aggregate, which makes the zoom selection fail.
Is there any way to link the x-axis of multiple charts so that all they zoom together and maintain the same x-axis range when one plot is zoomed?
Thanks!