c.uent
c.uent

Reputation: 115

Altair plot two stack bar charts side by side

I am trying to plot two different attributes side by side in a stack bar chart.

This is what I have:

import pandas as pd
from datetime import datetime 
from dateutil.relativedelta import relativedelta
import random
import altair as alt

df = pd.DataFrame(data={
    "date": [datetime.now()+relativedelta(month=+i) for i in range(5)],
    "label": random.choices(["positive", "negative"], k=5),
    "prediction": random.choices(["likely", "very_likely", "unlikely", "very_unlikely"], k=5),
    "indicator": random.choices(["0", "1"], k=5),
})
selection1 = alt.selection_multi(fields=["prediction"], bind="legend")
plot1 = (
    alt.Chart()
    .mark_bar()
    .encode(
        x=alt.X("count(prediction):O", title="count", stack="zero"),
        y=alt.Y("month(date):N", title=None),
        color=alt.Color("prediction:N", scale=alt.Scale(scheme="tableau10")),
        opacity=alt.condition(selection1, alt.value(1), alt.value(0.2)),
        tooltip="prediction:N",
    )
    .add_selection(selection1)
)

selection2 = alt.selection_multi(fields=["label"], bind="legend")
plot2 = (
    alt.Chart()
    .mark_bar()
    .encode(
        x=alt.X("count(label):O", title="count", stack="zero"),
        y=alt.Y("month(date):N", title=None),
        color=alt.Color("label:N", scale=alt.Scale(scheme="tableau10")),
        opacity=alt.condition(selection2, alt.value(1), alt.value(0.2)),
        tooltip="label:N",
    )
    .add_selection(selection2)
)

text = (
    alt.Chart()
    .mark_text(dx=-15, dy=3, color="white")
    .encode(
        x=alt.X("count(prediction):O", title="label count", stack="zero"),
        y=alt.Y("month(date):N", title=None),
        detail="sipredictionte:N",
        text=alt.Text("count(prediction):Q", format=".1f"),
    )
)

plot = alt.layer((plot1+plot2)+text, data=df).facet(
    column=alt.Column("indicator", title="title"),
)

This code generates the following plot:

enter image description here

This is somewhat what I am trying to plot and I am not sure if it is possible with altair.

enter image description here

Basically, I have two fields that I want to plot side by side for each month in a column based. For each bin, I'd like to know the counts for each legend.

Upvotes: 0

Views: 367

Answers (2)

c.uent
c.uent

Reputation: 115

Changing the plot to Candlestick Chart, where y1 is prediction and y2 is label seems to work for my use case.

Upvotes: 0

LazyClown
LazyClown

Reputation: 822

Grouped bar chart works a little differently in Altair. You need to use a row and column combination. To get what you are looking for, you should use your Y-axis variable as a row variable as well. Something like this

selection1 = alt.selection_multi(fields=["prediction"], bind="legend")
plot1 = (
    alt.Chart()
    .mark_bar()
    .encode(
        x=alt.X("count(prediction):O", title="count", stack="zero",axis=alt.Axis(ticks=False, domain=False)),
        y=alt.Y("month(date):N", title=None),
        color=alt.Color("prediction:N", scale=alt.Scale(scheme="tableau10")),
        opacity=alt.condition(selection1, alt.value(1), alt.value(0.2)),
        tooltip="prediction:N",
    )
    .add_selection(selection1)
)

selection2 = alt.selection_multi(fields=["label"], bind="legend")
plot2 = (
    alt.Chart()
    .mark_bar()
    .encode(
        x=alt.X("count(label):O", title="",axis=None),
        y=alt.Y("label:N", title=None),
        color=alt.Color("label:N", scale=alt.Scale(scheme="tableau10")),
        opacity=alt.condition(selection2, alt.value(1), alt.value(0.2)),
        tooltip="label:N",
    )
    .add_selection(selection2)
)

text = (
    alt.Chart()
    .mark_text(dx=-15, dy=3, color="white")
    .encode(
        x=alt.X("count(prediction):O", title="label count", axis=None),
        y=alt.Y("month(date):N", title=None, axis=None),
        detail="sipredictionte:N",
        text=alt.Text("count(prediction):Q", format=".1f"),
    )
)

plot = alt.layer((plot1+plot2)+text, data=df
).facet(
    column=alt.Column("indicator", title="title",),
    row = alt.Row("month(date):N", title='')

).resolve_scale(
    y='independent'
).configure_axis(
    grid=False, 
    domain=False,
    ticks=False, 
).configure_view(
    strokeWidth=0
).configure_header(
    labels=False
)
plot

enter image description here

Upvotes: 1

Related Questions