I want to generate a 'double ended' barchart, showing gained points (of some metric) vis-a-vis missed points, something like this:
I managed to do this
import altair as alt
import pandas as pd
source = pd.DataFrame(
{
"cohort": ["A", "B", "C", "D", "E", "F", "G", "H", "I"],
"gained": [28, 55, 43, 91, 81, 53, 19, 87, 52],
"missed": [5, 8, 34, 21, 16, 22, 9, 7, 11],
}
)
up = (
alt.Chart(source)
.mark_bar(color="blue")
.encode(
x=alt.X("cohort:N").axis(labels=False, title=None, ticks=False),
y=alt.Y("gained:Q"),
)
)
down = (
alt.Chart(source)
.mark_bar(color="red")
.encode(
x=alt.X("cohort:N").axis(labelAngle=0),
y=alt.Y("missed:Q", scale=alt.Scale(reverse=True)),
)
)
alt.vconcat(up, down).resolve_scale(x="shared")
Is there any way I can remove the gap? Or perhaps go about it completely differently with Vega-Altair?
@r-beginners pointed me in the right direction, this does the trick:
import altair as alt
import pandas as pd
source = pd.DataFrame(
{
"cohort": [
"start",
"1st trimester",
"2nd trimester",
"3rd trimester",
"delivery",
],
"gained": [28, 55, 43, 11, 41],
"missed": [5, 8, 34, 21, 16],
}
)
WIDTH = 500
TEXT_OFFSET = 9
base_up = alt.Chart(source).encode(
x=alt.X("cohort:N").axis(None), y=alt.Y("gained:Q").axis(None), text="gained:Q"
)
up = base_up.mark_bar() + base_up.mark_text(align="center", dy=-TEXT_OFFSET).properties(
width=WIDTH
)
middle = (
alt.Chart(source)
.encode(
alt.X("cohort:N").axis(None),
alt.Text("cohort:N"),
)
.mark_text()
.properties(height=15, width=WIDTH)
)
base_down = alt.Chart(source).encode(
x=alt.X("cohort:N").axis(None),
y=alt.Y("missed:Q", scale=alt.Scale(reverse=True)).axis(None),
text="missed:Q",
)
down = base_down.mark_bar(color="red") + base_down.mark_text(
align="center", dy=TEXT_OFFSET
).properties(width=WIDTH)
alt.vconcat(up, down, spacing=0).configure_view(strokeOpacity=0)