Search code examples
altair

Scaling values in Altair to fit on layer?


I have a graph of stock prices and a layer with Earnings Expected and Earnings Actual.

The issue is the stock price can be $50 or $100 where the earnings values are usually within a couple dollars like $0.50 or $1.00. I'd like to layer both since dates line up nicely but earnings values are way smaller so they are always on the bottom of the graph.

enter image description here

I looked at alt.Scale() to make the earnings (green and gray circles) disregard the "Close price" and scale the circles higher.

Is there an attribute in Scale which can help or another function in Altair?

Here's my code for the Earnings chart portion:

expected_chart = alt.Chart(earnings_df).mark_point(
      size=point_size, 
      strokeWidth=stroke_size, 
      color="gray"
      ).encode(
        x=x_axis,
        y=alt.Y("EstimatedEarning:Q", axis=alt.Axis(labels=True), 
                scale=alt.Scale(domain=[min_earning, max_earning], type="log")),
        tooltip=tooltip,
  ).transform_filter(date_filter).properties(title=f"Earnings beat quarterly {symbol_name}",
               height=height,
               width=500)

Solution

  • It sounds like you want a dual y-axis with independent y-scales as in this example:

    import altair as alt
    from vega_datasets import data
    
    source = data.seattle_weather()
    
    base = alt.Chart(source).encode(
        alt.X('month(date):T').axis(title=None)
    )
    
    area = base.mark_area(opacity=0.3, color='#57A44C').encode(
        alt.Y('average(temp_max)').title('Avg. Temperature (°C)', titleColor='#57A44C'),
        alt.Y2('average(temp_min)')
    )
    
    line = base.mark_line(stroke='#5276A7', interpolate='monotone').encode(
        alt.Y('average(precipitation)').title('Precipitation (inches)', titleColor='#5276A7')
    )
    
    alt.layer(area, line).resolve_scale(
        y='independent'
    )