更改 Altair 中折线图的重叠顺序

use*_*757 5 python vega-lite altair

我在 Altair 中生成折线图。我想控制哪些行位于行堆栈的“顶部”。在我的示例中,我希望红线位于顶部(最新日期),然后下降到黄色(最旧日期)位于底部。

在此输入图像描述

我试图用sortof 的参数来控制它alt.Color ,但无论sort='ascending'sort='descending'线重叠的顺序都不会改变。

我怎样才能控制这个?希望我可以在不对源数据帧本身进行排序的情况下完成此操作。

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()
Run Code Online (Sandbox Code Playgroud)

joe*_*lom 4

默认情况下,图形标记按照它们在数据框中出现的顺序绘制(正如您所指出的),这意味着数据框中最后的元素将最后绘制并最终位于图表的顶部(称为最高“层”或最高的“z 顺序”):

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'
)
Run Code Online (Sandbox Code Playgroud)

在此输入图像描述

设置sort颜色编码的参数时,您不会更改点的 z 顺序,而只是更改为它们分配颜色的顺序。在下图中,“point2”仍然位于顶部,但它现在是蓝色而不是橙色:

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

在此输入图像描述

如果我们想更改 z 顺序以使“point1”位于顶部,我们必须使用编码来指定order

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

在此输入图像描述

但是,正如您在 Vega-Lite 文档中所读到的,编码order对于堆叠标记和路径标记(包括线标记)具有特殊行为,它控制点在一条线上连接的顺序,而不是它们的 z 排序/分层。

因此,我相信实现所需行为的唯一方法是对该列进行排序。您可以在图表构建期间执行此操作:

alt.Chart(df).mark_line(size=10).encode(
    x='a',
    y='b',
    color='c'
)
Run Code Online (Sandbox Code Playgroud)

在此输入图像描述

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

在此输入图像描述