下面的数据+示例演示了如何标记最高的条形。但是,它假设条形图是直接使用
matplotlib
绘制的,并且数据是 numpy
数组。如果您使用 pandas
或其他绘图库生成绘图,则需要修改下面的方法。
import pandas as pd
import numpy as np
import matplotlib.pyplot as plt
#Synthetic data
np.random.seed(0)
month_names = pd.Series(
pd.date_range(start='2023-01', periods=12, freq='M')
).dt.month_name().to_list()
month_names = [name[:3].upper() for name in month_names]
disturbances = np.stack([
np.random.randn(12) * 4 + 50, #orange bars
np.random.randn(12) * 6 + 50], #blue bars
axis=0
)
totals = disturbances.sum(axis=0) #total per month
#Plot
f, ax = plt.subplots(figsize=(10, 4))
bottom = np.zeros(12)
for dist in disturbances:
bars = ax.bar(month_names, dist, bottom=bottom, label='')
bottom += dist + 1.5
ax.xaxis.set_tick_params(rotation=45)
ax.set_xlabel('Month')
ax.set_ylabel('Disturbances')
#Make labels
#All labels empty except the largest value
labels = [''] * 12
labels[totals.argmax()] = totals[totals.argmax()].round()
ax.bar_label(bars, labels=labels);
.pivot_table
聚合每个组的 mean
,并创建一个单独的变量 tot
表示相对于 index
的最大总条高度。
pivot_table
索引将是 x 轴,列标题将是条形组。pandas.DataFrame.plot
与 kind='bar'
和 stacked=True
提供了绘制堆叠条形图的最简单选项。 pandas
使用 matplotlib
作为默认绘图后端。这个答案和这个答案中的说明使用
.bar_label
来注释条形。
fmt
参数是一个lambda
表达式,用于过滤标签以匹配tot
。这适用于 matplotlib v3.7
,否则必须使用自定义 label
参数。ax.containers
中,其中 ax.containers[0]
是底部段,ax.containers[1]
是顶部段。python 3.12.0
、pandas 2.1.2
、matplotlib 3.8.1
、seaborn 0.13.0
import seaborn as sns # seaborn is only used for the sample data, but pandas and matplotlib are imported as dependencies
import numpy # for sample data
# sample data: this is a pandas.DataFrame
df = sns.load_dataset('flights')[['month', 'passengers']]
df['Gender'] = np.random.choice(['Male', 'Female'], size=len(df))
# pivot and aggregate the mean
pt = df.pivot_table(index='month', columns='Gender', values='passengers', aggfunc='mean')
# calculate the max value by the index
tot = pt.sum(axis=1).max()
# plot the stacked bars
ax = pt.plot(kind='bar', stacked=True, rot=0, xlabel='Month',
ylabel='Mean Number of Passengers', title='Annotation Demonstration', figsize=(7, 5))
# annotate the top group of bars
ax.bar_label(ax.containers[1], fmt=lambda x: f'${x:0.2f}' if x == tot else '')
# move the legend: cosmetics
ax.legend(title='Gender', bbox_to_anchor=(1, 0.5), loc='center left', frameon=False)
# remove the top and right spines: cosmetics
ax.spines[['top', 'right']].set_visible(False)
tips.head()
month passengers Gender
0 Jan 112 Male
1 Feb 118 Female
2 Mar 132 Female
3 Apr 129 Male
4 May 121 Male
pt
Gender Female Male
month
Jan 264.000000 197.250000
Feb 212.333333 257.666667
Mar 234.333333 306.000000
Apr 275.833333 258.333333
May 337.000000 206.666667
Jun 307.000000 318.200000
Jul 339.666667 363.000000
Aug 324.000000 389.000000
Sep 274.200000 322.571429
Oct 243.833333 289.333333
Nov 233.571429 231.800000
Dec 183.500000 277.500000