微信公众号搜"智元新知"关注
微信扫一扫可直接关注哦!

Matplotlib:使用时间轴动画散点图

如何解决Matplotlib:使用时间轴动画散点图

我使用 this question 制作了这样的动画散点图

import matplotlib.pyplot as plt
import pandas as pd
from matplotlib.collections import PathCollection


df = pd.DataFrame({"x": [1,2,6,4,5,6],"y": [1,36,16,25,36]})
plt.ion()
fig: plt.figure = plt.figure
ax = fig.subplots()
path_collection: PathCollection = ax.scatter(df.loc[0:2,"x"],df.loc[0:2,"y"])
# Note: I don't use pandas built in DataFrame.plot.scatter function so I can get the PathCollection object to later change the scatterpoints.
fig.canvas.draw()
path_collection.set_offsets([[row.x,row.y] for index,row in df.loc[3:].iterrows()])
# Due to the format of offset (array-like (N,2)) this seems to be the best way to provide the data.

fig.canvas.draw()

这很完美,但我想在 x 轴上有时间,所以我尝试将上面的代码更改为:

import matplotlib.pyplot as plt
import pandas as pd
from matplotlib.collections import PathCollection

df = pd.DataFrame({'time': [pd.Timestamp('2021-02-04 00:00:01'),pd.Timestamp('2021-02-04 00:00:02'),pd.Timestamp('2021-02-04 00:00:10'),pd.Timestamp('2021-02-04 00:00:05'),pd.Timestamp('2021-02-04 00:00:06'),pd.Timestamp('2021-02-04 00:00:08')],'y': [5,10,8,9,10]})
fig: plt.figure = plt.figure()
ax = fig.subplots()
sc: PathCollection = ax.scatter(df.loc[0:2,"time"],"y"])
fig.canvas.draw()    
sc.set_offsets([[row.time,row in df.loc[3:].iterrows()])

fig.canvas.draw()

倒数第二行抛出这个错误TypeError: float() argument must be a string or a number,not 'Timestamp'。这似乎是由于 PathCollection 将其 _offsets 存储为一个不能包含 Timestamp 的 numpy 数组。 所以我想知道,有没有办法用时间轴为散点设置动画?

提前致谢。

解决方法

对于任何有同样问题的人,我找到了一个可能远非理想的解决方案,但它可以完成工作。 事实证明,PathCollection 将时间存储为 np.float64,表示自 1/1/0001 以来的天数。而且由于使用 set_offset 似乎只能用于大小为 (N,2) 的类数组对象,因此我将 pd.Timestamp 重新调整为自 1/1/0001 以来的几天,如下所示:

time = pd.Timestamp('2021-02-04 00:00:01')
sec_since_1970 = time.timestamp()           # pd.Timestamp.timestamp() gives seconds since epox.
days_since_1970 = sec_since_1970/60/60/24   # Seconds to days.
days_since_0001 = days_since_1970 + 719163  # 719163 = number of days from 1/1/0001 until 1/1/1970  

在问题中实现这一点给出了以下内容:

df = pd.DataFrame({'time': [pd.Timestamp('2021-02-04 00:00:01'),pd.Timestamp('2021-02-04 00:00:02'),pd.Timestamp('2021-02-04 00:00:10'),pd.Timestamp('2021-02-04 00:00:05'),pd.Timestamp('2021-02-04 00:00:06'),pd.Timestamp('2021-02-04 00:00:08')],'y': [5,6,10,8,9,10]})
data = [[719163 + row.time.timestamp()/60/60/24,row.y] for index,row in df.loc[3:].iterrows()]
sc.set_offsets(data)
# Set axis limits
ax.set_ylim(bottom=df.y.loc[3:].min() -1,top=df.y.loc[3:].max()+1)
ax.set_xlim(left= (df.time.loc[3:].min().timestamp()-1)/60/60/24+719163,right=(df.time.loc[3:].max().timestamp()+1)/60/60/24+719163)
fig.canvas.draw()

所以这解决了问题,这可能不是最有效的方法,但对于小数据集,它工作正常。

版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 dio@foxmail.com 举报,一经查实,本站将立刻删除。