altair
altair copied to clipboard
Arc based charts (i.e. Pie or Radial charts) layered text not aligned
I have attempting to make a few simple pie charts with an added text that indicates percentages. An issue I have run into is the alignment of the text, where the text is not aligned with the appropriate parts of the pie chart. Here is the code below:
color_scale = alt.Scale(
domain=["Android","iOS"],
range=["#9F7F9F","#31AFD4"]
)
base = alt.Chart(df).encode(
theta=alt.Theta("count():Q",stack=True),
color=alt.Color("device_type:N",
legend=alt.Legend(title=None,
orient="none",
direction="horizontal",legendX=-10,legendY=-30),
scale=color_scale,
),tooltip="count():Q",
).properties(
title=alt.Title(text="Apple or Android?",offset=10),
height=200,
)
pie = base.mark_arc(outerRadius=80)
text = base.mark_text(
radius=100,
size=10,
).transform_aggregate(
count="count():Q",
groupby=['device_type']
).transform_joinaggregate(
total_devices='sum(count)',
).transform_calculate(
perc="datum.count / datum.total_devices",
).encode(
text=alt.Text("perc:Q",format=".2%",),
color=alt.value("#605E5C"),
tooltip=alt.Text("count:Q"),
)
device_chart = alt.layer(pie, text)
and the resulting chart looks like this (notice the inconsistency of the text):
I have played around with the theta and offset parameters to no luck, is this resolvable?
Please follow these steps to make it more efficient to solve your issue:
- [x] Since Altair is a Python wrapper around the Vega-Lite visualization grammar, most bugs should be reported directly to Vega-Lite. You can click the Action Button of your Altair chart and "Open in Vega Editor" to create a reproducible Vega-Lite example and see if you get the same error in the Vega Editor.
- [x] Search for duplicate issues.
- [x] Use the latest version of Altair.
- [ x Describe how to reproduce the bug and include the full code and data to reproduce it, ideally using a sample data set from
vega_datasets
.
Hi @robml , I reproduce this issue using Altair version 5.1.2:
df = pd.DataFrame({"device_type": ["Android", "iOS", "iOS", "iOS", "iOS", "iOS", "iOS", "iOS"]})
color_scale = alt.Scale(
domain=["Android","iOS"],
range=["#9F7F9F","#31AFD4"]
)
base = alt.Chart(df).encode(
theta=alt.Theta("count():Q",stack=True),
color=alt.Color("device_type:N",
legend=alt.Legend(title=None,
orient="none",
direction="horizontal",legendX=-10,legendY=-30),
scale=color_scale,
),tooltip="count():Q",
).properties(
title=alt.Title(text="Apple or Android?",offset=10),
height=200,
)
pie = base.mark_arc(outerRadius=80)
text = base.mark_text(
radius=100,
size=10,
align="center",
).transform_aggregate(
count="count():Q",
groupby=['device_type']
).transform_joinaggregate(
total_devices='sum(count)',
).transform_calculate(
perc="datum.count / datum.total_devices",
).encode(
text=alt.Text("perc:Q",format=".2%",),
color=alt.value("#605E5C"),
tooltip=alt.Text("count:Q"),
)
pie+text
results in
that the text does not overlap with the pie chart.
Another approach is place the text at the center of the arc
# Adjust the data frame format
df['number'] = df.groupby(['device_type'])['device_type'].transform('count')
df = df.drop_duplicates()
color_scale = alt.Scale(
domain=["Android","iOS"],
range=["#9F7F9F","#31AFD4"]
)
base = alt.Chart(df).encode(
theta=alt.Theta("number",stack=True),
color=alt.Color("device_type:N",
legend=alt.Legend(title=None,
orient="none",
direction="horizontal",legendX=-10,legendY=-30),
scale=color_scale,
),tooltip="number:Q",
).properties(
title=alt.Title(text="Apple or Android?",offset=10),
height=200,
)
pie = base.mark_arc(outerRadius=80)
text = base.mark_text(
radius=100,
size=10,
align="center",
).transform_joinaggregate(
total_devices='sum(number)',
).transform_calculate(
perc="datum.number / datum.total_devices",
).encode(
text=alt.Text("perc:Q",format=".2%",),
color=alt.value("#605E5C"),
tooltip=alt.Text("number:Q"),
)
pie+text
But I'm not sure why using transform_aggregate()
does not center the text automatically.