Маркировка слоистых диаграмм на Альтаире (Python) - PullRequest
0 голосов
/ 26 января 2020

Я пытаюсь создать две многослойные гистограммы в Альтаире (и среднюю вертикальную линейку для каждой). Мне бы хотелось, чтобы легенда обозначала каждую из этих четырех.

Я использую первые данные «Вес при рождении I», которые можно найти здесь

Мой код (реальный долго, извиняюсь) выглядит примерно так:

from altair import datum

# This histogram for baby weights of mothers who dont smoke
dont = alt.Chart(babyData).mark_bar().encode(
    alt.X("bwt-oz:Q", axis=alt.Axis(title='Birth Weight (Ounces)'), bin=True),
    alt.Y('count()', axis=alt.Axis(title='Count'), scale=alt.Scale(domain=[0, 350]))
).properties(
    width=400,
    height=400
).transform_filter(
    datum.smoke == 0,
)

mean = alt.Chart(babyData).mark_rule(color='red').encode(
    x='mean(bwt-oz):Q',
    size=alt.value(4)
).transform_filter(
    datum.smoke == 0
)

dontSmokeChart = dont + mean

# This histogram for baby weights of mothers who smoke
do = alt.Chart(babyData).mark_bar().encode(
    alt.X("bwt-oz:Q", axis=alt.Axis(title='Birth Weight (Ounces)'), bin=True),
    alt.Y('count()', axis=alt.Axis(title='Count'), scale=alt.Scale(domain=[0, 350]))
).transform_filter(
    datum.smoke == 1
).properties(
    width=400,
    height=400
)

mean2 = alt.Chart(babyData).mark_rule(color='red').encode(
    x='mean(bwt-oz):Q',
    size=alt.value(4)
).transform_filter(
    datum.smoke == 1
)

doSmokeChart = do + mean2

# This layers, and puts them all together

layer = alt.layer(
    dont,
    mean,
    do,
    mean2
).properties(
    title="Layered Histogram of Baby Weights of Mothers Who smoke Vs. Who Don't",
).configure_mark(
    opacity=0.5,
    color='blue',
)
layer

Окончательный многоуровневый график выглядит примерно так: https://i.stack.imgur.com/OR9f4.png

Я бы просто хотел легенда, указывающая, какому гистограмме / среднему значению принадлежит.

Если бы я мог их раскрасить и, возможно, добавить легенду таким образом, это было бы также неплохо, но я не уверен, как это сделать.

Спасибо за понимание!

Ответы [ 2 ]

3 голосов
/ 28 января 2020

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

Например:

import altair as alt
import pandas as pd

babyData = pd.read_csv('https://www.stat.berkeley.edu/users/statlabs/data/babiesI.data', delim_whitespace=True)

base = alt.Chart(babyData).transform_filter(
    'datum.smoke != 9'
)

hist = base.mark_bar(opacity=0.5).encode(
    alt.X("bwt:Q",title='Birth Weight (Ounces)', bin=True),
    alt.Y('count()', title='Count'),
    color='smoke:N'
).properties(
    width=400,
    height=400
)

mean = base.mark_rule().encode(
    x='mean(bwt):Q',
    size=alt.value(4),
    color='smoke:N'
)

hist + mean

enter image description here

Оттуда вы можете использовать стандартные подходы к Настройка цветовых схем , используемых для каждой марки.

2 голосов
/ 28 января 2020

@ jakevdp, просто побей меня до этого! Я собирался сказать то же самое. Вот полный пример для работы с вами.

import pandas as pd
import altair as alt

# Link to data source
URL =  'https://www.stat.berkeley.edu/users/statlabs/data/babiesI.data'
# Read data into a pandas dataframe
df = pd.read_table(URL, sep='\s+')

hist = alt.Chart(df).mark_area(
    opacity=0.7,
    interpolate='step'
).encode(
    alt.X("bwt:Q", axis=alt.Axis(title='Birth Weight (Ounces)'), bin=True),
    alt.Y('count()', axis=alt.Axis(title='Count'), stack=None), 
    alt.Color('smoke:N')
).properties(
    width=400,
    height=400
).transform_filter(alt.datum.smoke != 9)

rule = alt.Chart(df).mark_rule(color='red').encode(
    alt.Detail('smoke:N'),
    alt.Color('smoke:N'),
    alt.X('mean(bwt):Q'),
    size=alt.value(4), 
).transform_filter(alt.datum.smoke != 9)

hist + rule

...