在Python中创建比例堆积条形图

问题描述 投票:0回答:1

我正在尝试创建一个比例堆积条形图,其中包含 (6) 个类别,总计为 100。我有一个数据框,其中六个类别 (C1) 中的每个类别都有一年中每个月的多个值 (n = 12) 、C2、C3、C4、C5、C6)。

我尝试使用 matplotlib m.patches 来组装每个条形的平均值,并得出下图。我想将每个条形堆叠在一起。目前,它们彼此叠放。

是否有任何简单的添加/修改可以让我堆叠条形?

代码和尝试的条形图:

# import libraries
import seaborn as sns
import numpy as np
import matplotlib.pyplot as plt
import matplotlib.patches as mpatches

df = pd.read_csv('marsh fig 7.csv')
plt.rcParams["axes.labelsize"] = 12
plt.figure(figsize=(600/my_dpi, 300/my_dpi), dpi=my_dpi)

bar1 = sns.barplot(x="Month",  y="Percent_C1", data=df,     color='darkgreen')
bar2 = sns.barplot(x="Month",  y="Percent_C2", data=df,     color='mediumseagreen')
bar3 = sns.barplot(x="Month",  y="Percent_C3", data=df,     color='goldenrod')
bar4 = sns.barplot(x="Month",  y="Percent_C4", data=df,     color='sienna')
bar5 = sns.barplot(x="Month",  y="Percent_C5", data=df,     color='steelblue')
bar6 = sns.barplot(x="Month",  y="Component Proportion",     data=df, color='darkblue')

# add legend
bar1 = mpatches.Patch(color='darkgreen', label='% C1')
bar2 = mpatches.Patch(color='mediumseagreen', label='% C2')
bar3 = mpatches.Patch(color='goldenrod', label='% C3')
bar4 = mpatches.Patch(color='sienna', label='% C4')
bar5 = mpatches.Patch(color='steelblue', label='% C5')
bar6 = mpatches.Patch(color='darkblue', label='% C6')
plt.ylim(0,40)
plt.text(0, 39, "Marsh", ha='left', va='top',fontsize=12,     fontweight='normal', color="black")

ax2 = plt.twinx()
df2 = pd.read_csv('SRS1 Water Level.csv')
ax = sns.pointplot(x="Month", y="Water Depth (cm)", data=df2,         color="black", linestyles=':', label=None, errwidth=1,     capsize=0.2)   

plt.legend(handles=[bar1, bar2, bar3, bar4, bar5, bar6])
plt.show()
python matplotlib seaborn bar-chart stacked-bar-chart
1个回答
0
投票

here it is

import matplotlib.pyplot as plt
import numpy as np 
np.random.seed(20240801)

values = np.random.randint(1, 9, (12, 6)) # Fake some data

m = 'Jan Feb Mar Apr May Jun Jul Aug Sep Oct Nov Dec'.split()
colors = 'darkgreen mediumseagreen goldenrod sienna steelblue darkblue'.split()

# equivalent to data = open('….csv').read()
data = '\n'.join(
    ['Month C1 C2 C3 V4 C5 C6'] +
    [mon+' '+' '.join(str(v) for v in val) for mon, val in zip(m, values)]
    )

# reorder data as "read" from file into a dictionary
labels, *data = [line.strip().split() for line in data.split('\n') if line]
month, *cn = labels
data = dict(zip(labels, zip(*data)))

# convert list of strings to arrays of floats
for c in cn: data[c] = np.array(data[c]).astype(float)
############################################################################
# Here it is the actual answer to your question as I've understood it
bottom = np.zeros(len(data[c]))
totals_by_month = np.array([sum(data[c][n] for c in cn) for n in range(12)])
for label in cn:
    values = data[label]/totals_by_month
    plt.bar(data[month], values,
            label=label, bottom=bottom, ec='k', lw=0.5, color=colors.pop(0))
    bottom += values
plt.legend()
plt.show()
© www.soinside.com 2019 - 2024. All rights reserved.