首页 > 解决方案 > How to plot y-axis bands in Altair charts?

问题描述

Can Altair plot bands on the y axis, similar to this Highcharts example?

The docs have an example showing how to draw a line on the y axis, but adapting the example to use plot_rect to draw a band instead doesn't quite work:

import altair as alt
from vega_datasets import data

weather = data.seattle_weather.url

chart = alt.Chart(weather).encode(
    alt.X("date:T")
)

bars = chart.mark_bar().encode(
    y='precipitation:Q'
)

band = chart.mark_rect().encode(
    y=alt.value(20),
    y2=alt.value(50),
    color=alt.value('firebrick')
)

alt.layer(bars, band)

plot_rect with fixed y and y2

标签: pythonaltair

解决方案


我认为当你给出一个值时的问题alt.value是你从图的顶部开始以像素为单位指定值:它没有映射到数据。

在最初的答案中mark_rule,它不会创建一个干净的带,而是创建很多垂直条纹,所以这是一种正确绘制带的方法。

第一个解决方案是为乐队创建一个全新的数据框,并将其叠加在条形顶部:

import altair as alt
import pandas as pd
from vega_datasets import data

weather = data('seattle_weather')
band_df = pd.DataFrame([{'x_min': weather.date.min(),
                         'x_max': weather.date.max(),
                         'y_min': 20,
                         'y_max': 50}])

bars = alt.Chart(weather).mark_bar().encode(
    x=alt.X('date:T'),
    y=alt.Y('precipitation:Q', title="Precipitation")
)

band_2 = alt.Chart(band_df).mark_rect(color='firebrick', opacity=0.3).encode(
    x='x_min:T',
    x2='x_max:T',
    y='y_min:Q',
    y2='y_max:Q'
)

alt.layer(bars, band_2)

在此处输入图像描述

第二个选项,如果您不想/不能创建数据框,请使用,并在带状图中transform_calculate手动指定x和:x2

bars = alt.Chart().mark_bar().encode(
    x=alt.X('date:T', title='Date'),
    y=alt.Y('precipitation:Q', title="Precipitation")
)

band_3 = alt.Chart().mark_rect(color='firebrick', opacity=0.3).encode(
    x='min(date):T',
    x2='max(date):T',
    y='y_min:Q',
    y2='y_max:Q'
).transform_calculate(y_min='20', y_max='50')

alt.layer(bars, band_3, data=data.seattle_weather.url)

在此处输入图像描述

初步答案

我会做两件事来模仿你给出的高图示例。首先,使用 atransform_calculate来设置y_miny_max值。其次,我将使用mark_rule带跨度在有值的 X 轴上。(我还添加了一些不透明度并更改了图层的顺序,以便条带位于条形后面。)

import altair as alt
from vega_datasets import data

weather = data.seattle_weather.url

chart = alt.Chart().encode(
    alt.X("date:T")
)

bars = chart.mark_bar().encode(
    y='precipitation:Q'
)

band = chart.mark_rule(color='firebrick',
                       opacity=0.3).encode(
    y=alt.Y('y_min:Q'),
    y2=alt.Y('y_max:Q')
).transform_calculate(y_min="20",
                      y_max="50")


alt.layer(band, bars, data=weather)

altair_plot_with_band


推荐阅读