Business
Jobs
  • About Us
  • Solutions
    • Job Postings
      Post your job and receive qualified candidates in 48h.
    • Candidate Assessments
      500+ technical and psychological tests, plus anti-fraud.
    • Headhunting
      Tailor-made executive search from start to finish.
    • Payroll + EOR
      Payroll dispersal and EOR across 15+ LATAM countries.
  • Pricing
  • Jobs

0

245
Views
Changing overlap order of a line chart in altair

I generate a line chart in Altair. I'd like to control which lines are "on top" of the stack of lines. In my example here, I wish for the red line to be on top (newest date) and then descend down to the yellow (oldest date) to be on the bottom.

enter image description here

I tried to control this with the sort parameter of of alt.Color but regardless of sort='ascending' or sort='descending' the order of the line overlap will not change.

How can I control this? Was hoping I can do this without sorting my source dataframe itself.

data = [{'review_date': dt.date(year=2022, month=2, day=24),  'a':19, 'b':17, 'c':12, 'd':8},
{'review_date': dt.date(year=2022, month=2, day=23),  'a':20, 'b':16, 'c':14, 'd':8},
{'review_date': dt.date(year=2022, month=2, day=22),  'a':22, 'b':16, 'c':14, 'd':10},
{'review_date': dt.date(year=2022, month=2, day=21),  'a':14, 'b':13, 'c':12, 'd':5},]

df = pd.DataFrame(data).melt(id_vars=['review_date'], value_name='price', var_name='contract')
df.review_date = pd.to_datetime(df.review_date)

domain = df.review_date.unique()
range_ = ['red', 'blue', 'gray', 'yellow'] 

alt.Chart(df, title='foo').mark_line().encode(
x=alt.X('contract:N'),
y=alt.Y('price:Q',scale=alt.Scale(zero=False)),
color=alt.Color('review_date:O', sort="ascending", scale=alt.Scale(domain=domain, range=range_)   )
).interactive()
over 4 years ago · Santiago Trujillo
1 answers
Answer question

0

By default, graphical marks are plotted in the order they occur in the dataframe (as you noted), which means that the elements last in the dataframe will be plotted last and end up on top in the chart (called the highest "layer" or the highest "z-order"):

import pandas as pd
import altair as alt


df = pd.DataFrame({
    'a': [1, 2, 1, 2],
    'b': [1.1, 2.1, 1.0, 2.2],
    'c': ['point1', 'point1', 'point2', 'point2']
})

alt.Chart(df).mark_circle(size=1000).encode(
    x='a',
    y='b',
    color='c'
)

enter image description here

When you set the sort parameter of the color encoding, you are not changing the z-order for the dots, you are only changing the order in which they are assigned a color. In the plot below, "point2" is still on top, but it is now blue instead of orange:

alt.Chart(df).mark_circle(size=1000).encode(
    x='a',
    y='b',
    color=alt.Color('c', sort='descending')
)

enter image description here

If we wanted to change the z-ordering so that "point1" is on top, we would have to specify this with the order encoding:

alt.Chart(df).mark_circle(size=1000).encode(
    x='a',
    y='b',
    color='c',
    order=alt.Order('c', sort='descending')
)

enter image description here

However, as you can read in the Vega-Lite documentation the order encoding has a special behavior for stacked and path marks, including line mark, where it controls the order in which the points are connected in a line rather than their z-ordering/layering.

Therefore, I believe the only way you can achieve the desired behavior is by sorting that column. You can do this during chart construction:

alt.Chart(df).mark_line(size=10).encode(
    x='a',
    y='b',
    color='c'
)

enter image description here

alt.Chart(df.sort_values('c', ascending=False)).mark_line(size=10).encode(
    x='a',
    y='b',
    color='c'
)

enter image description here

over 4 years ago · Santiago Trujillo Report
Answer question
Find remote jobs

Discover the new way to find a job!

Top jobs
Top job categories
Business
Post vacancy Pricing Sales
Legal
Terms and conditions Privacy policy
© 2026 PeakU Inc. All Rights Reserved.
Andres GPT
Show me some job opportunities
There's an error!