创建 100% 堆积条形图

Agu*_*ina 3 python matplotlib bar-chart stacked-chart seaborn

我需要生成 100% 堆积条形图,包括分布百分比(不带小数)或观测值数量。

我的数据集如下所示:

在此输入图像描述

我需要生成一个不同的数据来计算每月的活动量和迟到量:

在此输入图像描述

然后使用第二个数据框生成我的 100% 堆积条形图(应该看起来像这样)

在此输入图像描述

有人有一个简单的方法来做到这一点吗?

谢谢!!

Qua*_*ang 9

您可以尝试value_counts()标准化:

(df.groupby('Date')['Status'].value_counts(normalize=True)
   .unstack('Status').plot.bar(stacked=True)
)
Run Code Online (Sandbox Code Playgroud)


Fed*_*ico 6

您可以使用下面的代码生成以下图表。另请考虑阅读答案直到最后,我解释了为什么水平条形图可能更好。

在此输入图像描述

我的数据集如下所示:

热感圆形 热偏好
0 2 冷却器
1 2 冷却器
2 0 不用找了
3 0 不用找了
4 1 更温暖

我使用以下代码来生成绘图。在代码中我正在执行以下步骤:

  1. 对数据进行分组、对条目进行计数并对它们进行标准化
  2. 使用 Pandas 函数绘制数据.plot.bar(stacked=True)
  3. 将图例放在顶部
  4. 使用for循环将格式化文本添加到图表中。请注意,如果低于 10%,我不会打印百分比,您可以更改它。
  5. 用于tight_layout()使图像居中。
    x_var, y_var = "thermal_sensation_round", "thermal_preference"
    df_grouped = df.groupby(x_var)[y_var].value_counts(normalize=True).unstack(y_var)
    df_grouped.plot.bar(stacked=True)
    plt.legend(
        bbox_to_anchor=(0.5, 1.02),
        loc="lower center",
        borderaxespad=0,
        frameon=False,
        ncol=3,
    )
    for ix, row in df_grouped.reset_index(drop=True).iterrows():
        cumulative = 0
        for element in row:
            if element == element and element > 0.1:
                plt.text(
                    ix,
                    cumulative + element / 2,
                    f"{int(element * 100)} %",
                    va="center",
                    ha="center",
                )
            cumulative += element
    plt.tight_layout()
Run Code Online (Sandbox Code Playgroud)

水平堆积条形图

使用水平条形图是一个更好的主意,因为它会更容易读取百分比。请参阅下面的示例。

在此输入图像描述

要做到这一点非常简单,只需将bar函数替换为barh. 请注意,您需要反转文本函数中的 x 和 y 坐标。请找到下面的代码。

    x_var, y_var = "thermal_sensation_round", "thermal_preference"
    df_grouped = df.groupby(x_var)[y_var].value_counts(normalize=True).unstack(y_var)
    df_grouped.plot.barh(stacked=True)
    plt.legend(
        bbox_to_anchor=(0.5, 1.02),
        loc="lower center",
        borderaxespad=0,
        frameon=False,
        ncol=3,
    )
    for ix, row in df_grouped.reset_index(drop=True).iterrows():
        print(ix, row)
        cumulative = 0
        for element in row:
            if element == element and element > 0.1:
                plt.text(
                    cumulative + element / 2,
                    ix,
                    f"{int(element * 100)} %",
                    va="center",
                    ha="center",
                )
            cumulative += element
    plt.tight_layout()
Run Code Online (Sandbox Code Playgroud)