Definition: Kreisdiagramm

Ein Kreisdiagramm (en. Pie Chart) ist ein Diagrammtyp, der verwendet wird, um Daten in Form von Anteilen oder Prozentsätzen zu visualisieren.

Es besteht aus einem Kreis, der in verschiedene Sektoren unterteilt ist, wobei jeder Sektor einen Teil des Ganzen repräsentiert und die Größe jedes Sektors proportional zum Anteil des Gesamtdatenwertes ist.

  • Regeln:
    • Die Daten müssen in Summe “ein Ganzes” ergeben.
    • Es sollte maximal 5 Segmente geben.
    • Das größte Segment sollte oben in der Mitte (i.e. 12 Uhr) anfangen. Die restlichen Segmente sollten im Uhrzeigersinn hinzugefügt werden.
    • Die Proportionen sollten “alltägliche” Proportionen wie x/2, x/3, x/4 umfassen.

Anmerkung

Kritik

Kreisdiagramme werden oft dafür kritisiert, dass sie schwer zu lesen sind.

Die Größe der Segmente ist - insbesondere bei sehr vielen Segmenten - kaum unterscheidbar.

Beispielsweise:

Kreisdiagramm mit matplotlib

In Python erhalten wir ein (bzw. mehrere) Kreisdiagramm durch

from typing import Optional
import matplotlib.pyplot as plt
import math
import seaborn as sns
 
sns.set_palette("pastel")
 
 
def sort_lists(sort_by_list: list, *lists: list):
    return zip(*sorted(zip(sort_by_list, *lists)))
 
 
def plot_pie(
    title: str,
    value_counts: list[int],
    label_map: list[str],
    axis: plt.Axes,
    color_map: dict[str, tuple[float]],
):
    labels = [label_map[label] for label in value_counts.index]
    color_palette = [color_map[label] for label in value_counts.index]
 
    sorted_value_counts, sorted_labels, sorted_color_palette = sort_lists(
        value_counts, labels, color_palette
    )
 
    axis.set_title(title, size=11)
    axis.pie(
        sorted_value_counts,
        labels=sorted_labels,
        startangle=90,
        autopct="%.1f%%",
        colors=sorted_color_palette,
    )
 
 
def choose_labels(
    default_labels: list[str], custom_labels: Optional[list[str]]
) -> list[str]:
    labels = custom_labels or sorted(default_labels)
 
    assert len(labels) == len(
        default_labels
    ), f"expected: {len(default_labels)} labels, actual: {len(labels)} labels. default_labels: {default_labels}, custom_labels: {custom_labels}"
 
    return {
        default_label: label
        for label, default_label in zip(labels, sorted(default_labels))
    }
 
 
def plot_multi_pie(
    figtitle: str,
    df: pd.DataFrame,
    label_dim: str,
    value_dim: str,
    nrows: int,
    figsize: int,
    custom_dim_labels: Optional[list[str]] = [],
    custom_value_labels: Optional[list[str]] = [],
    dpi: int = 250,
):
    # Get labels
    default_labels = list(df[label_dim].unique())
    display_label_map = choose_labels(default_labels, custom_dim_labels)
 
    default_value_labels = sorted(list(df[value_dim].unique()))
    value_label_map = choose_labels(default_value_labels, custom_value_labels)
 
    palette = sns.color_palette(n_colors=len(value_label_map))
    color_map = {label: palette[i] for i, label in enumerate(default_value_labels)}
 
    # Create subplots
    ncols = math.ceil(len(default_labels) / nrows)
    fig, axes = plt.subplots(nrows, ncols, figsize=(figsize, figsize), dpi=dpi)
    axes = axes.flatten()
 
    # Create pie plots
    for label, current_axis in zip(default_labels, axes):
        value_counts = df[df[label_dim] == label].value_counts(value_dim)
 
        plot_pie(
            display_label_map[label],
            value_counts,
            value_label_map,
            current_axis,
            color_map,
        )
 
    # Hide any unused subplots
    for ax in axes[len(display_label_map) :]:
        ax.set_visible(False)
 
    # fig.tight_layout()
    fig.suptitle(figtitle, size=20)
    fig.show()
 
plot_multi_pie(
    figtitle="Interesse nach Abteilungen",
    df=df,
    label_dim="abteilung",
    value_dim="interesse",
    nrows=2,
    figsize=10,
    dpi=250,
    # Optional: custom_dim_labels=["Küche", "IT", "Verwaltung", "Entwicklung", "Marketing"],
    # Optional: custom_value_labels=["Kein Interesse", "Interesse"],
)