vega / altair

Declarative statistical visualization library for Python
https://altair-viz.github.io/
BSD 3-Clause "New" or "Revised" License
9.22k stars 784 forks source link

Misaaligned labels on Altair pie chart #2909

Open ZEOwen opened 1 year ago

ZEOwen commented 1 year ago

When adding text labels to a pie chart, they will sometimes be off center no matter what variables are changed on the mark_text call.

base_chart = alt.Chart(graph_source).encode(
            theta=alt.Theta(field="Annotations", type="quantitative", stack=True),
            color=alt.Color(field="Degrees", type="nominal"),
        )
pie = base_chart.mark_arc()
text = base_chart.mark_text(radius=140, size=18, align="center", baseline="middle", fontStyle="bold",
                                             tooltip=False)\
            .encode(text="Annotations", color=alt.value("#FFFFFF"))
return pie + text

This creates the resulting pie:

image

What should happen is each text label is in the center of each wedge of the pie chart.

Additional details:

mattijn commented 1 year ago

Seen this https://github.com/altair-viz/altair/discussions/2887?

mattijn commented 1 year ago

I see, you already use stack=True. Can you include a code snippet including data, or even better use one of the existing examples to showcase the problem eg. https://altair-viz.github.io/gallery/pie_chart_with_labels.html

ZEOwen commented 1 year ago

It happens when I add the color tag to the mark text. I need to change the color to white as I am nesting the labels inside the pie wedges on the actual graph. Any ideas how to fix this?

Edit: Adding the color also changes the order of the labels as they appear on the pie chart.

Edit2: I fixed this by changing pie = base.mark_arc(outerRadius=120) to pie = base.mark_arc(outerRadius=120).encode(order=alt.Order(field="value"))

So the bug is likely that changing the color also changes the order of the encoded values.

image

source = pd.DataFrame(
            {"category": ["a", "b", "c", "d", "e", "f"], "value": [4, 6, 10, 3, 7, 8]}
        )

        base = alt.Chart(source).encode(
            theta=alt.Theta("value:Q", stack=True), color=alt.Color("category:N", legend=None)
        )

        pie = base.mark_arc(outerRadius=120)
        text = base.mark_text(radius=140, size=20).encode(text="value:Q", color=alt.value("#FFFFFF"))

        return pie + text