Jorge
Jorge

Reputation: 48

Altair - link y-axis with x-axis of a different chart

I need to visually compare two signals and I'm using Altair to plot some interactive charts like the example below.

import altair as alt
import pandas as pd
import numpy as np

np.random.seed(42)

df_comparison = pd.DataFrame({'x1': np.arange(20), 'x2': np.arange(20)}) #just for example purposes, actual data will be more interesting
df_signal_1 = pd.DataFrame({'x1': np.arange(20), 'data_1': np.random.random(20)})
df_signal_2 = pd.DataFrame({'x2': np.arange(20), 'data_2': np.random.random(20)})

comparison = alt.Chart(df_comparison, title='Comparison').mark_point(filled=True).encode(
    alt.X('x1'),
    alt.Y('x2')
).interactive()

signal_1 = alt.Chart(df_signal_1,title='Signal 1').mark_line().encode(
    alt.X('x1'),
    alt.Y('data_1'),
)

signal_2 = alt.Chart(df_signal_2, title='Signal 2').mark_line().encode(
    alt.X('x2'),
    alt.Y('data_2'),
)

(signal_1 & (comparison | signal_2).resolve_scale(x='shared')).resolve_scale(x='shared')

Altair charts

By zooming the Comparison chart you can see that its "x1" axis is linked to the "x1" axis of Signal 1, which is fine. However, it is also linked to "x2" axis of Signal 2 and that is not good. How can I link the "x2" axes of the Comparison and Signal 2 charts without breaking the link between the "x1" axes?

Upvotes: 1

Views: 580

Answers (1)

jakevdp
jakevdp

Reputation: 86533

You can do this by creating the interaction manually, and then linking domains to the selection's encodings; something like this:

x12_zoom = alt.selection_interval(encodings=['x', 'y'], bind='scales')

comparison = alt.Chart(df_comparison, title='Comparison').mark_point(filled=True).encode(
    alt.X('x1'),
    alt.Y('x2'),
).add_selection(x12_zoom)

signal_1 = alt.Chart(df_signal_1,title='Signal 1').mark_line().encode(
    alt.X('x1', scale=alt.Scale(domain={'selection': x12_zoom.name, 'encoding': 'x'})),
    alt.Y('data_1'),
)

signal_2 = alt.Chart(df_signal_2, title='Signal 2').mark_line().encode(
    alt.X('x2', scale=alt.Scale(domain={'selection': x12_zoom.name, 'encoding': 'y'})),
    alt.Y('data_2'),
)

(signal_1 & (comparison | signal_2))

enter image description here

Upvotes: 1

Related Questions