Python 设置渐变条形图动画-matplotlib

Python 设置渐变条形图动画-matplotlib,python,pandas,matplotlib,animation,Python,Pandas,Matplotlib,Animation,下面的代码为条形图设置动画。我正在尝试将渐变和文本标签应用到这个动画中。autolabel()函数用于添加文本标签,gradientbar()函数用于添加渐变。然而,当应用here函数时,动画只生成一个静止图像 我也希望调整梯度到一个固定点。具体来说,我希望应用最大级别6,而不是将渐变应用到单个条高度的范围。关于这一点,请参见下图 我已经注释掉了下面的特定函数,因此代码可以工作,但应用它们将生成所附的图 fig, ax = plt.subplots() ax.grid(False) data

下面的代码为条形图设置动画。我正在尝试将渐变和文本标签应用到这个动画中。
autolabel()
函数用于添加文本标签,
gradientbar()
函数用于添加渐变。然而,当应用here函数时,动画只生成一个静止图像

我也希望调整梯度到一个固定点。具体来说,我希望应用最大级别6,而不是将渐变应用到单个条高度的范围。关于这一点,请参见下图

我已经注释掉了下面的特定函数,因此代码可以工作,但应用它们将生成所附的图

fig, ax = plt.subplots()
ax.grid(False)

data = np.random.randint(5, size=(10, 5))

x = ['A','B','C','D','E']
plt.ylim(0, 6)

rects = plt.bar(x, data[0])

def autolabel(rects):

    '''
    Attach a text label above each bar displaying its height
    '''
    for rect in rects:
        height = rect.get_height()
        ax.text(rect.get_x() + rect.get_width()/2., 1.05 * height,
                '%d' % int(height),
                ha = 'center', va = 'bottom')

def gradientbars(bars):

    grad = np.atleast_2d(np.linspace(0,5,256)).T

    cmap = 'Blues'
    
    ax = bars[0].axes
    lim = ax.get_xlim() + ax.get_ylim()

    for bar in bars:
    
        bar.set_zorder(1)
        bar.set_facecolor("none")
    
        x,y = bar.get_xy()
        w,h = bar.get_width(), bar.get_height()    
   
        ax.imshow(grad, extent = [x, x + w, y, y + h], aspect = "auto", zorder = 0, cmap = cmap)
    
    ax.axis(lim)

#autolabel(rects)

#gradientbars(rects)

def animate(i):

    for rect, yi in zip(rects, data[i]):
        rect.set_height(yi)

anim = animation.FuncAnimation(fig, animate, frames = len(data), interval = 100)

plt.show()

我会这样做:

def autolabel(rects):
    '''
    Attach a text label above each bar displaying its height
    '''
    ts = []
    for rect in rects:
        height = rect.get_height()
        t = ax.text(rect.get_x() + rect.get_width()/2., 1.05 * height,
                '%d' % int(height),
                ha = 'center', va = 'bottom')
        ts.append(t)
    return ts

def gradientbars(bars, cmap, vmin, vmax):
    g = np.linspace(vmin,vmax,100)
    grad = np.vstack([g,g]).T
    xmin,xmax = ax.get_xlim()
    ymin,ymax = ax.get_ylim()
    ims = []
    for bar in bars:
        bar.set_facecolor('none')
        im = ax.imshow(grad, aspect="auto", zorder=0, cmap=cmap, vmin=vmin, vmax=vmax, extent=(xmin,xmax,ymin,ymax))
        im.set_clip_path(bar)
        ims.append(im)
    return ims

Nbars=5
Nframes=10
vmin=0
vmax=6
cmap = 'Blues'
data = np.random.choice([0,1,2],size=(Nframes,Nbars))
data = data.cumsum(axis=1)
data[data>6] = 6
x=[chr(ord('A')+i) for i in range(Nbars)]
print(x)
print(data)

fig, ax = plt.subplots()
ax.grid(False)
plt.ylim(vmin, vmax)
rects = plt.bar(x,data[0])
labels = autolabel(rects)
imgs = gradientbars(rects, cmap=cmap, vmin=vmin, vmax=vmax)

def animate(i):
    for rect,label,img,yi in zip(rects, labels, imgs, data[i]):
        rect.set_height(yi)
        label.set_text('%d'%int(yi))
        label.set_y(yi)
        img.set_clip_path(rect)

anim = animation.FuncAnimation(fig, animate, frames = len(data), interval = 500)
plt.show()

编辑 负数也一样

Nbars = 5
Nframes = 50
dt=50
cmap='coolwarm_r'
data = np.zeros(shape=(Nframes,Nbars))
for i in range(Nbars):
    d = np.sin(np.arange(0,Nframes*(dt*1e-3),dt*1e-3)*0.5*np.pi+np.random.uniform(low=-1., high=1.))
    data[:,i] = d
x = [chr(ord('A')+i) for i in range(Nbars)]
vmin = -1.
vmax = 1.


def gradientbars(bars, cmap, vmin, vmax):
    g = np.linspace(vmin,vmax,100)
    grad = np.vstack([g,g]).T
    xmin,xmax = ax.get_xlim()
    ymin,ymax = ax.get_ylim()
    ims = []
    for bar in bars:
        bar.set_facecolor('none')
        im = ax.imshow(grad, aspect="auto", zorder=0, cmap=cmap, vmin=vmin, vmax=vmax, extent=(xmin,xmax,ymin,ymax))
        im.set_clip_path(bar)
        ims.append(im)
    return ims

def autolabel(rects):
    '''
    Attach a text label above each bar displaying its height
    '''
    ts = []
    for rect in rects:
        height = rect.get_height()
        va = 'bottom' if height>=0 else 'top'
        t = ax.text(rect.get_x() + rect.get_width()/2., height,
                f'{height:.2f}',
                ha ='center', va=va)
        ts.append(t)
    return ts


with plt.style.context('dark_background'):
    fig, ax = plt.subplots()
    ax.set_ylim(vmin,vmax)

    rects = ax.bar(x=x, height=data[0,:])
    imgs = gradientbars(rects, cmap, vmin, vmax)
    labels = autolabel(rects)
    sns.despine(ax=ax, left=True, right=True, bottom=True, top=True)
    ax.set_yticks([])


def animate(i, data, rects, imgs, labels):
    for j,(rect,img,label) in enumerate(zip(rects,imgs,labels)):
        rect.set_height(data[i,j])
        img.set_clip_path(rect)
        label.set_y(data[i,j])
        label.set_va('bottom' if data[i,j]>=0 else 'top')
        label.set_text(f'{data[i,j]:.2f}')

ani = animation.FuncAnimation(fig, animate, frames=Nframes, fargs=(data, rects, imgs, labels), interval=dt)

我会这样做:

def autolabel(rects):
    '''
    Attach a text label above each bar displaying its height
    '''
    ts = []
    for rect in rects:
        height = rect.get_height()
        t = ax.text(rect.get_x() + rect.get_width()/2., 1.05 * height,
                '%d' % int(height),
                ha = 'center', va = 'bottom')
        ts.append(t)
    return ts

def gradientbars(bars, cmap, vmin, vmax):
    g = np.linspace(vmin,vmax,100)
    grad = np.vstack([g,g]).T
    xmin,xmax = ax.get_xlim()
    ymin,ymax = ax.get_ylim()
    ims = []
    for bar in bars:
        bar.set_facecolor('none')
        im = ax.imshow(grad, aspect="auto", zorder=0, cmap=cmap, vmin=vmin, vmax=vmax, extent=(xmin,xmax,ymin,ymax))
        im.set_clip_path(bar)
        ims.append(im)
    return ims

Nbars=5
Nframes=10
vmin=0
vmax=6
cmap = 'Blues'
data = np.random.choice([0,1,2],size=(Nframes,Nbars))
data = data.cumsum(axis=1)
data[data>6] = 6
x=[chr(ord('A')+i) for i in range(Nbars)]
print(x)
print(data)

fig, ax = plt.subplots()
ax.grid(False)
plt.ylim(vmin, vmax)
rects = plt.bar(x,data[0])
labels = autolabel(rects)
imgs = gradientbars(rects, cmap=cmap, vmin=vmin, vmax=vmax)

def animate(i):
    for rect,label,img,yi in zip(rects, labels, imgs, data[i]):
        rect.set_height(yi)
        label.set_text('%d'%int(yi))
        label.set_y(yi)
        img.set_clip_path(rect)

anim = animation.FuncAnimation(fig, animate, frames = len(data), interval = 500)
plt.show()

编辑 负数也一样

Nbars = 5
Nframes = 50
dt=50
cmap='coolwarm_r'
data = np.zeros(shape=(Nframes,Nbars))
for i in range(Nbars):
    d = np.sin(np.arange(0,Nframes*(dt*1e-3),dt*1e-3)*0.5*np.pi+np.random.uniform(low=-1., high=1.))
    data[:,i] = d
x = [chr(ord('A')+i) for i in range(Nbars)]
vmin = -1.
vmax = 1.


def gradientbars(bars, cmap, vmin, vmax):
    g = np.linspace(vmin,vmax,100)
    grad = np.vstack([g,g]).T
    xmin,xmax = ax.get_xlim()
    ymin,ymax = ax.get_ylim()
    ims = []
    for bar in bars:
        bar.set_facecolor('none')
        im = ax.imshow(grad, aspect="auto", zorder=0, cmap=cmap, vmin=vmin, vmax=vmax, extent=(xmin,xmax,ymin,ymax))
        im.set_clip_path(bar)
        ims.append(im)
    return ims

def autolabel(rects):
    '''
    Attach a text label above each bar displaying its height
    '''
    ts = []
    for rect in rects:
        height = rect.get_height()
        va = 'bottom' if height>=0 else 'top'
        t = ax.text(rect.get_x() + rect.get_width()/2., height,
                f'{height:.2f}',
                ha ='center', va=va)
        ts.append(t)
    return ts


with plt.style.context('dark_background'):
    fig, ax = plt.subplots()
    ax.set_ylim(vmin,vmax)

    rects = ax.bar(x=x, height=data[0,:])
    imgs = gradientbars(rects, cmap, vmin, vmax)
    labels = autolabel(rects)
    sns.despine(ax=ax, left=True, right=True, bottom=True, top=True)
    ax.set_yticks([])


def animate(i, data, rects, imgs, labels):
    for j,(rect,img,label) in enumerate(zip(rects,imgs,labels)):
        rect.set_height(data[i,j])
        img.set_clip_path(rect)
        label.set_y(data[i,j])
        label.set_va('bottom' if data[i,j]>=0 else 'top')
        label.set_text(f'{data[i,j]:.2f}')

ani = animation.FuncAnimation(fig, animate, frames=Nframes, fargs=(data, rects, imgs, labels), interval=dt)

我不确定这里的问题是什么?为什么图形不是动画?如果你注释掉这两个函数,动画就会工作。应用这两个函数时,动画不起作用。我希望动画与这两个函数一起工作如果你对每个渐变应用相同的限制6,它们看起来就不再是动画了,是吗?我不确定这里的问题是什么?为什么图形不是动画?如果你注释掉这两个函数,动画就会工作。应用这两个函数时,动画不起作用。我想让动画与这两个功能一起工作如果你对每个渐变应用相同的限制6,它们看起来就不再是动画了,是吗?谢谢@Diziet Asahi。我只是尝试设置负整数标签的动画,使其位于条的顶部。我可以在静止图像上运行(请参见编辑2),但在动画图像开始时无法运行。我看到您发布了另一个问题,但我添加了适用于负数的代码。谢谢@Diziet Asahi。我只是尝试设置负整数标签的动画,使其位于条的顶部。我可以在静止图像上运行(请参见编辑2),但在动画图像开始时无法运行。我看到您发布了另一个问题,但我添加了同样适用于负数的代码