Skip to main content
 首页 » 编程设计

python之如何用箭头填充 pyplot 条形图的条形图

2025年05月04日23dflying

我正在尝试创建一个条形图,其中的条形图通过让条形图内的箭头指向基点来包含其他信息。

目前我只设法创建了一个带有彩色条的。由于方向需要 8 种颜色加上不存在的一种颜色,因此不如我希望的那么好。也有区分颜色的困难。

import matplotlib.pyplot as plt 
import numpy as np 
 
x = range(12) 
y_bar = np.random.random(12) 
 
colors = ['green', 'yellow', 'blue', 'pink', 'orange'] 
bar_cols = [ colors[int(b*100) % len(colors)] for b in y_bar] 
 
plt.bar(x, y_bar, color=bar_cols) 
plt.show() 

因此,指向由单独变量提供的方向的箭头是直观且易于查看的。

我不知道该怎么做。我已经尝试过使用舱口,但似乎只有一组有限的符号。

有没有办法在栏中添加一些箭头?

编辑: 这是一张图片,它看起来像什么,我在追求什么。箭头的形状可以不同。当然,预计会有更多支柱。由于任务数据,甚至可能有一些没有任何箭头。 barchar with arrows

请您参考如下方法:

这是一个使用 ax.annotate 在每个条形图内绘制箭头的解决方案。由于 OP 不太清楚箭头的外观,我将每个条形分成矩形(我在代码中称它们为 squares ,但如果固定长宽比,它们只是正方形plot) 并为每个矩形绘制一个居中箭头,其方向由用户提供的角度给出(此处在一个名为 wind_direction 的向量中)。

在代码中,我将 Axes 的纵横比设置为 x 和 y 的纵横比,这使得Axes 是方形的,因此可以很容易地绘制相同长度的箭头,而与它们的方向无关。如果不需要,可以注释掉相应的行。如果箭头必须具有相同的长度而没有该限制,则必须计算图形纵横比,例如参见here怎么做。

我还用度数的风向注释了每个条形,只是为了便于检查箭头是否与给定的风向相对应。

from matplotlib import pyplot as plt 
import numpy as np 
 
fig,ax = plt.subplots() 
 
x = np.arange(12) 
wind_strength = np.random.random(12) 
wind_direction = np.linspace(0,2*np.pi,12, endpoint = False) 
 
colors = ['green', 'yellow', 'blue', 'pink', 'orange'] 
bar_cols = [colors[i%len(colors)] for i,s in enumerate(wind_strength)] 
 
bars = ax.bar(x,wind_strength, color=bar_cols) 
 
##computing the aspect ratio of the plot ranges: 
xlim = ax.get_xlim() 
ylim = ax.get_ylim() 
aspect = (xlim[1]-xlim[0])/(ylim[1]-ylim[0]) 
 
 
##comment out this line if you don't care about the arrows being the 
##same length 
ax.set_aspect(aspect) 
 
 
##dividing each bar into 'squares' and plotting an arrow into each square 
##with orientation given by wind direction 
for bar,angle in zip(bars,wind_direction): 
    (x1,y1),(x2,y2) = bar.get_bbox().get_points() 
    w = x2-x1 
    h = w/aspect 
    x_mid = (x1+x2)/2 
 
    dx = np.sin(angle)*w 
    dy = np.cos(angle)*h 
 
    ##the top and bottom of the current square: 
    y_bottom = y1 
    y_top = y_bottom+h 
 
    ##draw at least one arrow (for very small bars) 
    first = True 
 
    while y_top < y2 or first: 
        y_mid = (y_top+y_bottom)/2 
 
        ax.annotate( 
            '',xytext=(x_mid-dx/2,y_mid-dy/2), 
            xy=(x_mid+dx/2,y_mid+dy/2), 
            arrowprops=dict(arrowstyle="->"), 
        ) 
 
        ##next square 
        y_bottom = y_top 
        y_top += h 
 
        ##first arrow drawn: 
        first = False 
 
    ##annotating the wind direction: 
    ax.text(x_mid, y2+0.05, '{}'.format(int(180*angle/np.pi)), ha = 'center') 
 
plt.show() 

最终结果是这样的:

希望这对您有所帮助。