问题
I am attempting to create two layered histograms in Altair (and a vertical mean ruler for each). I would like a legend to label each of these four.
I am using the first 'Birth weight I' data that can be found here
My code (real long, apologies) looks something like this:
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
The final layered chart looks something like this:
I would simply like a legend specifying which histogram/mean belongs to what.
If I could color them too, and perhaps add a legend that way, that would be nice as well, but I am unsure how to do so.
Thanks for any insight!
回答1:
Rather than manually creating layers with filtered data, you should use a color encoding on your full dataset: then a legend will be generated automatically.
For example:
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
From there you could use standard approaches to Customize the color schemes used for each mark.
回答2:
@jakevdp just beat me to it! I was going to say the same thing. Here is a full example for you to work with.
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
来源:https://stackoverflow.com/questions/59921991/labelling-layered-charts-in-altair-python