簡體   English   中英

如何從分類數據框創建 100% 堆疊條形圖

[英]How to create a 100% stacked barplot from a categorical dataframe

我有一個結構如下的數據框:

用戶 食物 1 食物 2 食物 3 食物 4
斯蒂芬 洋蔥 番茄 卷心菜 土豆
湯姆 土豆 番茄 土豆 土豆
弗雷德 蘿卜 卷心菜 茄子
菲爾 洋蔥 茄子 茄子

我想將食物列中的不同值用作類別。 然后我想創建一個 Seaborn 圖,以便將每列的每個類別的百分比繪制為 100% 水平堆疊條。

我嘗試這樣做:

data = {
    'User' : ['Steph', 'Tom', 'Fred', 'Phil'],
    'Food 1' : ["Onions", "Potatoes", "Carrots", "Onions"],
    'Food 2' : ['Tomatoes', 'Tomatoes', 'Cabbages', 'Eggplant'],
    'Food 3' : ["Cabbages", "Potatoes", "", "Eggplant"],
    'Food 4' : ['Potatoes', 'Potatoes', 'Eggplant', ''],    
}

df = pd.DataFrame(data)

x_ax = ["Onions", "Potatoes", "Carrots", "Onions", "", 'Eggplant', "Cabbages"]

df.plot(kind="barh", x=x_ax, y=["Food 1", "Food 2", "Food 3", "Food 4"], stacked=True, ax=axes[1])

plt.show()
  1. ''替換為np.nan因為空字符串將被計為值。
  2. 使用pandas.DataFrame.melt將數據幀轉換為長格式。
  3. 使用pandas.crosstab獲取頻率計數表
  4. 獲取每一行的總數。
  5. 計算每一行的類別百分比。
  6. 使用pandas.DataFrame.plotkind='barh' barh' 繪制數據框。
    • 將食物名稱放在 x 軸上並不是創建 100% 堆疊條形圖的正確方法。 一個軸必須是數字。 這些條將按食物類型着色。
  7. 根據這個答案對條形圖進行注釋。
  8. 根據這個答案將圖例移到情節之外。
  • seabornmatplotlib的高級 API, pandas使用matplotlib作為默認后端,使用pandas更容易生成堆積條形圖。
    • seaborn不支持堆疊條形圖,除非histplot以黑客方式使用,如this answer所示,並且需要額外的熔化percent步驟。
  • python 3.10pandas 1.4.2matplotlib 3.5.1中測試
    • 賦值表達式 ( := ) 需要python >= 3.8 否則,使用[f'{v.get_width():.2f}%' if v.get_width() > 0 else '' for v in c ]
import pandas as pd
import numpy as np

# using the dataframe in the OP

# 1.
df = df.replace('', np.nan)

# 2.
dfm = df.melt(id_vars='User', var_name='Food', value_name='Type')

# 3.
ct = pd.crosstab(dfm.Food, dfm.Type)

# 4.
total = ct.sum(axis=1)

# 5. 
percent = ct.div(total, axis=0).mul(100).round(2)

# 6.
ax = percent.plot(kind='barh', stacked=True, figsize=(8, 6))

# 7.
for c in ax.containers:
    
    # customize the label to account for cases when there might not be a bar section
    labels = [f'{w:.2f}%' if (w := v.get_width()) > 0 else '' for v in c ]
    
    # set the bar label
    ax.bar_label(c, labels=labels, label_type='center')

# 8.
ax.legend(bbox_to_anchor=(1, 1.02), loc='upper left')

在此處輸入圖像描述

數據框視圖

dfm

     User    Food      Type
0   Steph  Food 1    Onions
1     Tom  Food 1  Potatoes
2    Fred  Food 1   Carrots
3    Phil  Food 1    Onions
4   Steph  Food 2  Tomatoes
5     Tom  Food 2  Tomatoes
6    Fred  Food 2  Cabbages
7    Phil  Food 2  Eggplant
8   Steph  Food 3  Cabbages
9     Tom  Food 3  Potatoes
10   Fred  Food 3       NaN
11   Phil  Food 3  Eggplant
12  Steph  Food 4  Potatoes
13    Tom  Food 4  Potatoes
14   Fred  Food 4  Eggplant
15   Phil  Food 4       NaN

ct

Type    Cabbages  Carrots  Eggplant  Onions  Potatoes  Tomatoes
Food                                                           
Food 1         0        1         0       2         1         0
Food 2         1        0         1       0         0         2
Food 3         1        0         1       0         1         0
Food 4         0        0         1       0         2         0

total

Food
Food 1    4
Food 2    4
Food 3    3
Food 4    3
dtype: int64

percent

Type    Cabbages  Carrots  Eggplant  Onions  Potatoes  Tomatoes
Food                                                           
Food 1      0.00     25.0      0.00    50.0     25.00       0.0
Food 2     25.00      0.0     25.00     0.0      0.00      50.0
Food 3     33.33      0.0     33.33     0.0     33.33       0.0
Food 4      0.00      0.0     33.33     0.0     66.67       0.0

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM