Согласование шкал, осей и легенд

При создании составных диаграмм Altair по умолчанию использует общие шкалы и направляющие: оси, легенды и другие элементы. Это поведение можно изменить методами Chart.resolve_scale, Chart.resolve_axis и Chart.resolve_legend.

Предположим, нужно объединить две диаграммы с отдельными цветовыми шкалами. По умолчанию цветовая шкала строится по объединению диапазонов двух цветовых кодирований:

import altair as alt
from altair.datasets import data

source = data.cars()

base = alt.Chart(source).mark_point().encode(
    x='Horsepower:Q',
    y='Miles_per_Gallon:Q'
).properties(
    width=200,
    height=200
)

alt.concat(
    base.encode(color='Origin:N'),
    base.encode(color='Cylinders:O')
)

Чтобы изменить поведение, задайте для согласования цветовой шкалы "independent" вместо стандартного "shared":

alt.concat(
    base.encode(color='Origin:N'),
    base.encode(color='Cylinders:O')
).resolve_scale(
    color='independent'
)

Две оси y

Распространённый способ объединить разные показатели — использовать две оси y. В Altair есть два подхода. Первый: вручную задать цвет примитива и соответствующий цвет заголовка оси для каждого слоя:

import altair as alt
from altair.datasets import data

source = data.cars()

base = alt.Chart(source).encode(x='year(Year):T')

line_A = base.mark_line(color='#5276A7').encode(
    alt.Y('average(Horsepower):Q').axis(titleColor='#5276A7')
)

line_B = base.mark_line(color='#F18727').encode(
    alt.Y('average(Miles_per_Gallon):Q').axis(titleColor='#F18727')
)

alt.layer(line_A, line_B).resolve_scale(y='independent')

Здесь цвета осей заменяют легенду. Если нужна настоящая легенда, примените фильтрацию и преобразование Fold. Vega-Lite создаёт легенды только для представления кодирования.

base = alt.Chart(source).mark_line().transform_fold(
    ['Horsepower', 'Miles_per_Gallon'],
    as_=['Measure', 'Value']
).encode(
    alt.Color('Measure:N'),
    alt.X('year(Year):T')
)

line_A = base.transform_filter(
    alt.datum.Measure == 'Horsepower'
).encode(
    alt.Y('average(Value):Q').title('Horsepower')
)

line_B = base.transform_filter(
    alt.datum.Measure == 'Miles_per_Gallon'
).encode(
    alt.Y('average(Value):Q').title('Miles_per_Gallon')
)

alt.layer(line_A, line_B).resolve_scale(y='independent')

Диаграммы с двумя осями могут вводить в заблуждение относительно взаимосвязей данных. Подробнее об этом рассказывает статья Лизы Шарлотты Рост «The case against dual axis charts».