Как добавить слои на граненый график в Altair? - PullRequest
1 голос
/ 30 октября 2019

Altair - прекрасная библиотека визуализации, с приятным интуитивным API визуальной грамматики. Однако я изо всех сил пытаюсь добавить слой с метками правил на граненый график.

Представьте, что у вас есть простой набор данных:

print(df[['Year', 'Profile', 'Saison', 'Pos']].to_csv())
,Year,Profile,Saison,Pos
0,2017,6.0,Sommer,VL
1,2017,6.0,Winter,VL
13,2017,6.0,Winter,HL
12,2017,6.0,Sommer,HL
18,2017,6.0,Sommer,HR
6,2017,6.0,Sommer,VR
7,2017,6.0,Winter,VR
19,2017,6.0,Winter,HR
14,2018,5.5,Winter,HL
8,2018,5.5,Winter,VR
15,2018,5.5,Sommer,HL
20,2018,4.3,Winter,HR
21,2018,5.0,Sommer,HR
3,2018,5.5,Sommer,VL
2,2018,6.2,Winter,VL
9,2018,4.5,Sommer,VR
17,2019,4.5,Sommer,HL
11,2019,4.2,Sommer,VR
22,2019,3.5,Winter,HR
10,2019,5.28,Winter,VR
5,2019,4.6,Sommer,VL
4,2019,4.9,Winter,VL
16,2019,4.0,Winter,HL
23,2019,4.5,Sommer,HR

Чем вы можете просто отобразить его с помощью:

base = alt.Chart(df[df.Saison=='Winter']).mark_bar().encode(x='Year:O', y='Profile:Q', column='Pos:N')
base

enter image description here

Чем, скажем, я хочу добавить горизонтальные метки для визуализации некоторых ограничений:

enter image description here

Для этого я определяю DataSet:

print(Limits.to_csv())
,Profil
0,3.0
1,1.5

И добавляю его в коллекцию диаграмм:

limits = alt.Chart(Limits).mark_rule(color='red').encode(y='Profil')
base + limits

Это не работает и генерирует ошибку:

ValueError: Faceted charts cannot be layered.

Как мне преодолеть это ограничение? Основная грамматика vega-light, по-видимому, поддерживает такую ​​сложную композицию слоев, но я не могу понять, как выразить это в Альтаире.

1 Ответ

1 голос
/ 30 октября 2019

Нельзя нанести слой с фацетированной диаграммой, поскольку в общем случае нет гарантии, что содержимое каждого слоя содержит совместимые фасетки.

Однако вы можете огранить многослойную диаграмму. Это может выглядеть примерно так:

import altair as alt
import pandas as pd
import io

df = pd.read_csv(io.StringIO("""
,Year,Profile,Saison,Pos
0,2017,6.0,Sommer,VL
1,2017,6.0,Winter,VL
13,2017,6.0,Winter,HL
12,2017,6.0,Sommer,HL
18,2017,6.0,Sommer,HR
6,2017,6.0,Sommer,VR
7,2017,6.0,Winter,VR
19,2017,6.0,Winter,HR
14,2018,5.5,Winter,HL
8,2018,5.5,Winter,VR
15,2018,5.5,Sommer,HL
20,2018,4.3,Winter,HR
21,2018,5.0,Sommer,HR
3,2018,5.5,Sommer,VL
2,2018,6.2,Winter,VL
9,2018,4.5,Sommer,VR
17,2019,4.5,Sommer,HL
11,2019,4.2,Sommer,VR
22,2019,3.5,Winter,HR
10,2019,5.28,Winter,VR
5,2019,4.6,Sommer,VL
4,2019,4.9,Winter,VL
16,2019,4.0,Winter,HL
23,2019,4.5,Sommer,HR
"""))

bars = alt.Chart().mark_bar().encode(
    x='Year:O',
    y='Profile:Q',
)

limits = alt.Chart(
  pd.DataFrame({'Profil': [3, 1.5]})
).mark_rule(
  color='red'
).encode(y='Profil')

alt.layer(
    bars,
    limits,
    data=df[df.Saison=='Winter']
).facet(
    'Pos:N',
)

enter image description here

Задать данные здесь немного сложно: метод facet() отключает клавиши сверхуУровень данных в диаграмме, к которой он вызывается, поэтому, когда вы обрабатываете слои, построенные из разных наборов данных, вам необходимо указать соответствующие данные на верхнем уровне.

...