Search code examples
pythonaltair

Specify one series to be plotted on the secondary y axis


Say I have some data in a long format. There are three series represented by keys a, b and c.

The values of c are an order of magnitude higher than those of a and b.

In the following plot, is there a (simple) way to specify that c should be plotted on the secondary y axis?

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

df = (
    pd.DataFrame({
        'a': np.random.rand(10),
        'b': np.random.rand(10),
        'c': np.random.rand(10) * 10,
    })
    .stack()
    .to_frame('value')
    .reset_index()
)
df.columns = ['index', 'key', 'value']

(
    alt.Chart(df)
    .mark_line()
    .encode(x='index', y='value', color='key')
)

enter image description here


Solution

  • I'm not an expert and I'm sure there are more efficient approaches. I used a filter to layer each graph and added an independent setting for the y-axis.

    import altair as alt
    from altair import datum
    import numpy as np
    import pandas as pd
    
    np.random.seed(20200113)
    df = (
        pd.DataFrame({
            'a': np.random.rand(10),
            'b': np.random.rand(10),
            'c': np.random.rand(10) * 10,
        })
        .stack()
        .to_frame('value')
        .reset_index()
    )
    df.columns = ['index', 'key', 'value']
    
    base = alt.Chart(df).mark_line().encode(
        x='index',
        y='value',
        color='key:N'
        ).transform_filter(
        (datum.key == 'a') | (datum.key =='b')
    )
    
    line = alt.Chart(df).mark_line(color='#57A44C').encode(
        x='index',
        y=alt.Y('value', axis=alt.Axis(title='value')),
        color='key'
    ).transform_filter(
        (datum.key == 'c')
    )
    
    alt.layer(base, line).resolve_scale(
        y = 'independent'
    )
    

    enter image description here