Я пытаюсь сопоставить две линии на одной диаграмме в Altair, которые меняют цвет в середине графика.
Вот как должен выглядеть сюжет в идеале:
Пока я успешно построил две линии на одном графике. Каждая линия имеет собственный цвет, но цвета не меняются в средней точке.
Вот код: (1) фиктивная версия моих данных:
import pandas as pd
from datetime import datetime
import numpy as np
data_list = [(['1', '2']*20)*2,
[0]*20+[1]*20,
np.repeat(pd.date_range(datetime.today(), periods=20).tolist(), 2),
np.random.normal(size=40)
]
data_df = pd.DataFrame(data_list).transpose()
data_df.columns = ['group', 'post', 'datetime', 'value']
(2) Код Альтаира
PROPERTIES = {"height": 200, "width": 800}
line_chart_1 = (
alt.Chart(data_df)
.transform_calculate(group = "datum.group == '1' ? 'Group A:1' : 'Group B:1' ")
.transform_filter("datum.post == 0")
.mark_line(opacity=0.8, strokeWidth=3, strokeCap='round')
.encode(
alt.X("datetime:T", title=None),
alt.Y("value:Q", title=None),
alt.Color(
"group:N",
scale=alt.Scale(
domain=("Group A:1", "Group B:1"), range=("#F44E4E", "#0442BF")
),
title=None,
legend=alt.Legend(orient = "bottom-left"),
),
)
)
line_chart_2 = (
alt.Chart(data_df)
.transform_calculate(group = "datum.group == '1' ? 'Group A:2' : 'Group B:2' ")
.transform_filter("datum.post == 1")
.mark_line(opacity=0.8, strokeWidth=3, strokeCap='round')
.encode(
alt.X("datetime:T", title=None),
alt.Y("value:Q", title=None),
alt.Color(
"group:N",
scale=alt.Scale(
domain=("Group A:2", "Group B:2"), range=("#F20505", "#63CAF2")
),
title=None,
legend=alt.Legend(orient = "bottom-left"),
),
)
)
area_chart = (
alt.Chart(data_df)
.mark_rect(opacity=0.5)
.encode(
alt.X("start:T"),
alt.X2("stop:T"),
y=alt.value(0),
y2=alt.value(PROPERTIES["height"]),
fill=alt.Color(
"post:N",
scale=alt.Scale(domain=(0, 1), range=("lightgray", "lightgray")),
legend=None,
),
)
)
alt.layer(area_chart, line_chart_2, line_chart_1).properties(**PROPERTIES)
Я также видел этот пост и пробовал следующее:
line_chart = alt.layer(
alt.Chart().mark_line(),
alt.Chart().mark_line().encode(color='post:N'),
data=data_df
).transform_filter(
'datum.group== = "1"',
).encode(
x='datetime:T',
y=alt.Y('value:Q', impute = {'value': None}),
)
line_chart_2 = alt.layer(
alt.Chart().mark_line(),
alt.Chart().mark_line().encode(color='post:N'),
data=data_df
).transform_filter(
'datum.group== = "2"',
).encode(
x='datetime:T',
y=alt.Y('value:Q', impute = {'value': None}),
)
alt.layer(line_chart, line_chart_2)
Что меня очень близко, но я не могу понять, как изменить цвета сегментов линии или добавить легенду.
Кто-нибудь знает, как довести один из этих участков до финиша? Заранее спасибо за вашу помощь!
Вы должны явно указать, что вам нужны независимые легенды, используя функцию resolve_scale
. Я попытался запустить ваш код, но значения x
вашего mark_rect
отсутствуют. Используя только линейные графики, это будет выглядеть примерно так
alt.layer(line_chart_1, line_chart_2).properties(**PROPERTIES).resolve_scale(color='independent')