我有一个条形图,我想使用数据框中的数据动态更新。
原始图基于数据框,
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()
我想循环遍历第二个数据框,
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()
您当前的方法是在每个帧中重新绘制图形,这在使用
FuncAnimation
时会做一些有趣的事情。
相反,您需要:
update
方法进行手动调整。
您可以使用以下方式收集所有艺术家:from matplotlib.lines import Line2D
[a for a in ax.get_children() if isinstance(a,Line2D)]
例如,请参阅以下内容:
# 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-')
艺术家的数据。
备注:
我怀疑您打算做什么,您需要收集每位艺术家(可能在字典/列表中)并确保顺序正确才能按照 newDf 的描述更新艺术家。匹配这些可能有点愚蠢。您可以使用
[a.get_ydata() for a in ax.get_children() if hasattr(a,'get_ydata')]
来了解每个艺术家的位置,并确保顺序与您对 df.iterrows
函数的期望相符。
您想要的更新将需要根据您想要的内容对
artist
对象进行各种调用。我把这个留给你,因为有点不清楚你想要从这个问题中得到什么动画。但是删除艺术家、在艺术家中设置数据以及设置位置可能会包含在您需要的内容中。
从高层次来看,这是一个名为 blitting 的 matplotlib 概念,您可以在此处阅读更多相关信息:https://matplotlib.org/stable/users/explain/animations/blitting.html