如何计算每个直方图 bin 的总和和平均条

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

我想绘制堆叠条形图。前 3 个条是红色、黑色和蓝色,如下所示。

我想添加第四个条,它是红色、黑色和蓝色条的值的“总和”。

(在另一种情况下,我想添加第四个条,它是红色、黑色和蓝色条的“平均值”。)

例如,这是我的代码:

import numpy as np
import matplotlib.pyplot as plt

np.random.seed(19680801)

n_bins = 20
x = np.random.randn(1000, 3)

fig, ax0 = plt.subplots(nrows=1, ncols=1)

colors = ['red', 'black', 'blue']
ax0.hist(x, n_bins, density=True, histtype='bar', color=colors, label=colors)
ax0.legend(prop={'size': 10})
ax0.set_title('bars with legend')



fig.tight_layout()
plt.show()

这个数字没有第 4 个小节。

关于如何在此堆栈条形图中显示第 4 个条有什么建议吗?

python numpy matplotlib histogram grouped-bar-chart
1个回答
0
投票

使用

np.histogram
计算每组的
hist
bin_edges
,计算每组的总和和平均值,并绘制带有每个箱子绝对条高的条形图。

绘制分组或堆叠条形图的最简单方法是使用

pandas.DataFrame
pandas.DataFrame.plot
.

测试于

python 3.11.2
pandas 2.0.1
matplotlib 3.7.1
numpy 1.24.3

import numpy as np
import pandas as pd

# data
np.random.seed(19680801)
n_bins = 20
x = np.random.randn(1000, 3)

# calculate bin_edges for the combined values
_, be = np.histogram(x, bins=n_bins, density=True)

# calculate hist for each sample
data = {f's{i}': np.histogram(col, bins=be, density=True)[0] for i, col in enumerate(x.T)}

# round the values of the bin edges to be used as xtick labels in the plot
be = be.round(1)

# stack the arrays for each bin group
groups = np.column_stack(list(data.values()))

# calculate the total
data['tot'] = groups.sum(axis=1)

# calculate the mean
data['mean'] = groups.mean(axis=1)

# create a dataframe from data
df = pd.DataFrame(data=data)

# plot 
ax = df.plot(kind='bar', width=0.85, ec='k', figsize=(11, 6), rot=0)

# update the xticks by shifting them to the right by 0.5, and updating the labels
ax.set_xticks(ticks=np.arange(0, len(be))-0.5, labels=be)

# add some cosmetics
ax.grid(axis='x')
ax.spines[['right', 'top']].set_visible(False)
_ = ax.legend(bbox_to_anchor=(1, 0.5), loc='center left', frameon=False)

  • 使用
    .iloc
    y=['s0', 's1', 's2', 'mean']
    选择要绘制的特定列。
# plot 
ax = df.iloc[:, [0, 1, 2, 4]].plot(kind='bar', width=0.85, ec='k', figsize=(14, 6), rot=0)

# add some cosmetics
ax.set_xticks(ticks=np.arange(0, len(be))-0.5, labels=be)
ax.grid(axis='x')
ax.spines[['right', 'top']].set_visible(False)
_ = ax.legend(bbox_to_anchor=(1, 0.5), loc='center left', frameon=False)

# add some labels
for c in ax.containers:
    ax.bar_label(c, fmt=lambda x: f'{x:0.3f}' if x > 0.005 else '', label_type='edge', fontsize=6, rotation=90, padding=3)
    
ax.margins(y=0.15)

© www.soinside.com 2019 - 2024. All rights reserved.