When executing the following code I would expect the graph to not include zero, but instead start somewhere around the minimum point in the data shown on the y-axis.
import pandas as pd
import altair as alt
print(alt.__version__)
df = pd.DataFrame(data={"targets": ['A', 'B', 'C', 'D'], "values": [0.91, 0.95, 0.97, 0.9]})
display(df)
alt.Chart(df).mark_bar().encode(
x='targets:N',
y=alt.Y('values:Q').scale(zero=False)
)
But I get this:
When applying mean()
to the values I am showing on the y-axis, this solves my issue. But I don't understand why this is happening.
alt.Chart(df).mark_bar().encode(
x='targets:N',
y=alt.Y('mean(values):Q').scale(zero=False)
)
Does this suggest I should not use a bar chart for individual values?
Using a different encoding seems to support that. For example with a line the zero is excluded:
alt.Chart(df).mark_line().encode(
x='targets:N',
y=alt.Y('values:Q').scale(zero=False)
)
I think it has to do with the fact that bar charts are stacked by default (even when there is only one value) and the default stack is zero
(docs). So usingy=alt.Y('values:Q', stack=None).scale(zero=False),
works, but your lowest bar will become invisible (beneath the x axis).
For non-zero bar charts I prefer to use domainMin
instead as you can set some offset.
a = alt.Chart(df).mark_bar().encode(
x='targets:N',
y=alt.Y('values:Q', stack=None).scale(zero=False)
)
b = alt.Chart(df).mark_bar(clip=True).encode(
x='targets:N',
y=alt.Y('values:Q').scale(zero=False, domainMin=df['values'].min()*0.99)
)
a | b