Reputation: 115
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:
This is somewhat what I am trying to plot and I am not sure if it is possible with altair.
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
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
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
Upvotes: 1