如何在Python中动态更新条形图

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

我有一个条形图,我想使用数据框中的数据动态更新。

原始图基于数据框,

d

d

Position    Operation   Side    Price   Size
1   9   0   1   0.7289  -19
2   8   0   1   0.729   -427
3   7   0   1   0.7291  -267
4   6   0   1   0.7292  -18
5   5   0   1   0.7293  -16
6   4   0   1   0.7294  -16
7   3   0   1   0.7295  -429
8   2   0   1   0.7296  -23
9   1   0   1   0.7297  -31
10  0   0   0   0.7299  41
11  1   0   0   0.73    9
12  2   0   0   0.7301  10
13  3   0   0   0.7302  18
14  4   0   0   0.7303  16
15  5   0   0   0.7304  18
16  6   0   0   0.7305  429
17  7   0   0   0.7306  16
18  8   0   0   0.7307  268
19  9   0   0   0.7308  18

当通过下面的图绘制时,会返回:

f, ax = plt.subplots()
sns.set_color_codes('muted')

sns.barplot(data = d[d.Side==0], x = 'Size', y = 'Price', color = 'b', orient = 'h', native_scale=True)
sns.barplot(data = d[d.Side==1], x = 'Size', y = 'Price', color = 'r', orient = 'h', native_scale=True)
ax.yaxis.set_major_locator(ticker.MultipleLocator(.0001))
sns.despine()

enter image description here

我想循环遍历第二个数据框,

new_d
,以更新绘制的数据。

新_d

    Position    Operation   Side    Price   Size
34  0   1   0   0.7299  39
35  1   1   0   0.73    9
36  3   1   0   0.7302  18
37  0   1   1   0.7298  -8
38  0   1   1   0.7298  -9
39  0   1   1   0.7298  -8
40  0   1   1   0.7298  -9
41  0   1   1   0.7298  -14
42  0   1   1   0.7298  -9
43  0   2   1   0.0 0
44  9   0   1   0.7288  -17
45  0   1   1   0.7297  -29
46  1   1   1   0.7296  -23
47  9   2   1   0.0 0
48  0   0   1   0.7298  -3
49  1   1   1   0.7297  -31
50  0   1   1   0.7298  -10
51  0   1   0   0.7299  41
52  0   1   1   0.7298  -4
53  0   2   1   0.0 0
54  9   0   1   0.7288  -17
55  9   2   0   0.0 0
56  0   0   0   0.7298  2
57  0   1   0   0.7298  4
58  1   1   0   0.7299  39
59  0   1   0   0.7298  5

假设我有代码/逻辑将从

d
的行更新
new_d
,我如何动态更新我的绘图?

我已经使用

FuncAnimation
尝试了以下操作,但我认为我可能遗漏了一些东西。

def init():
    # f, ax = plt.subplots()
    sns.set_color_codes('muted')
   
    sns.barplot(data = d[d.Side==0], x = 'Size', y = 'Price', color = 'b', orient = 'h', native_scale=True)
    s = sns.barplot(data = d[d.Side==1], x = 'Size', y = 'Price', color = 'r', orient = 'h', native_scale=True)
    
    sns.despine()
    
    return s
    
    
def update_d(row):   
    
    if row.Operation == 1:
        d.loc[((d.Position==row.Position) & (d.Side==row.Side)), 'Size'] = row.Size
            
        
    elif row.Operation == 2:
        idx = d.loc[((d.Position==row.Position) & (d.Side==row.Side))].index
        d.drop(idx, inplace=True)
        
        
    elif row.Operation == 0:
        d = pd.concat([pd.DataFrame([[row.Time, row.Symbol, row.Position, row.Operation, row.Side, row.Price, row.Size]], columns=d.columns), d], ignore_index=True)
        d['Position'] = d.groupby('Side')['Price'].rank().astype('int').sub(1)        
        d.sort_values('Price', inplace=True)    

                  
    sns.barplot(data = d[d.Side==0], x = 'Size', y = 'Price', color = 'b', orient = 'h', native_scale=True)
    s = sns.barplot(data = d[d.Side==1], x = 'Size', y = 'Price', color = 'r', orient = 'h', native_scale=True)
     
    return s
 

f, ax = plt.subplots()
ax.yaxis.set_major_locator(ticker.MultipleLocator(.0001))
    
ani = FuncAnimation(f, update_d, init_func=init, frames=new_d[20:].iterrows(), interval = 100)

plt.show()
python matplotlib animation seaborn visualization
1个回答
0
投票

您当前的方法是在每个帧中重新绘制图形,这在使用

FuncAnimation
时会做一些有趣的事情。

相反,您需要:

  1. 在您想要制作动画的图表中抓取seaborn正在制作的实际艺术对象。需要美术人员通过
    update
    方法进行手动调整。 您可以使用以下方式收集所有艺术家:
from  matplotlib.lines import Line2D
[a for a in ax.get_children() if isinstance(a,Line2D)]
  1. 根据您的计划更新实际的艺术家对象。

例如,请参阅以下内容:

# Create the figure and axis
fig, ax = plt.subplots()
xdata, ydata = [], []
ln, = plt.plot([], [], 'b-')

# Initialization function for the plot
def init():
    ax.set_xlim(0, 2 * np.pi)
    ax.set_ylim(-1, 1)
    return ln,

# Update function to animate the plot
def update(frame):
    xdata.append(frame)
    ydata.append(np.sin(frame))
    ln.set_data(xdata, ydata)
    return ln,

# Create the animation
ani = FuncAnimation(
    fig, update, frames=np.linspace(0, 2 * np.pi, 128),
    init_func=init, blit=False
)

plt.show()

在此示例中,

update
函数正在设置来自
Line2D
ln, = plt.plot([], [], 'b-')
艺术家的数据。

备注:

  1. 我怀疑您打算做什么,您需要收集每位艺术家(可能在字典/列表中)并确保顺序正确才能按照 newDf 的描述更新艺术家。匹配这些可能有点愚蠢。您可以使用

    [a.get_ydata() for a in ax.get_children() if hasattr(a,'get_ydata')]
    来了解每个艺术家的位置,并确保顺序与您对
    df.iterrows
    函数的期望相符。

  2. 您想要的更新将需要根据您想要的内容对

    artist
    对象进行各种调用。我把这个留给你,因为有点不清楚你想要从这个问题中得到什么动画。但是删除艺术家、在艺术家中设置数据以及设置位置可能会包含在您需要的内容中。

从高层次来看,这是一个名为 blitting 的 matplotlib 概念,您可以在此处阅读更多相关信息:https://matplotlib.org/stable/users/explain/animations/blitting.html

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