我正试图绘制一段时间内几个空气污染传感器的读数。在第一种情况下,每个传感器的位置(纬度,长度)固定在散点图上,但在一天的不同时间或一年中的不同时间,颜色会根据污染程度而变化。 (在更高级的情况下,情况相同,但使用移动传感器,因此坐标将随时间变化并且颜色将随时间变化)。我在初始化和动画功能中使用'set_data'时遇到问题
我在SO和matplotlib文档的网上找到了大多数示例,这些示例与绘制动画折线图而不是散点图有关。标识为重复的链接涉及同一主题,但发现第一个选项很复杂,很难适应我自己相当简单的需求。给出的第二个解决方案给了我NameError: name 'xrange' is not defined
,这已经证明是具有挑战性的,因为seaborn和散点图似乎与行的代码结构不同。因此,我问了这个问题。
我的最初目标是使用固定x和y的seaborn散点图,但根据污染程度在每个帧中更改色相(请参见下面的代码),但是设置初始化函数时似乎出现问题
AttributeError:“ AxesSubplot”对象没有属性“ set_data”
我随后尝试使用x,y和facecolors作为变量的matplotlib散点图,但存在相同的问题
import pandas as pd
import numpy as np
import seaborn as sns
import matplotlib.pyplot as plt
import matplotlib.animation as animation
import random
%matplotlib notebook
# Suppose 3 fixed sensors, each with a result every day for 5 days
days = sorted(list(range(5))*3)
channel = (list(range(3)))*5
long = (random.sample(range(10, 20), 3))*5
lat = (random.sample(range(25, 35), 3))*5
colours = ['green', 'yellow', 'orange', 'red', 'brown']
colour = random.choices(colours, k=15)
# create dataframe
data = pd.DataFrame(list(zip(days, channel, long, lat, colour)), columns = ['day', 'sensor', 'x', 'y', 'colour'] )
# Set up the plot to be animated
fig, ax = plt.subplots(figsize=(10,10))
plt.xlim(10, 20)
plt.xlabel('Longitude',fontsize=20)
plt.ylim(25, 35)
plt.ylabel('Latitude',fontsize=20)
plt.title('Daily changes in pollution levels',fontsize=20)
p = sns.scatterplot([], [], hue= [], markers='o',s=500, ax=ax)
for i, txt in enumerate(data.sensor):
ax.annotate(txt, xy=(data.x[i], data.y[i]), textcoords='offset points', xytext=(10,10), fontsize=20, weight='bold')
# initialization function
def init():
# creating an empty plot/frame
p.set_data([], [], [])
return p
# animation function
def animate(i):
# x, y, hue values to be plotted
for j in range(0,3):
x = data.loc[(data.day ==i) & (data.sensor ==j), 'x']
y = data.loc[(data.day ==i) & (data.sensor ==j), 'y']
hue = data.loc[(data.day ==i) & (data.sensor ==j), 'colour']
# set/update the x and y axes data
p.set_data(x, y, hue)
# return plot object
return p
# call the animator
anim = animation.FuncAnimation(fig, animate, init_func=init, frames=15, interval=20, blit=True)
plt.show()
# save the animation as mp4 video file
anim.save('sensors.mp4', writer = 'ffmpeg', fps = 5)
我怀疑还有其他错误,但是最大的障碍是错误消息AttributeError:当我尝试保存动画时,“ AxesSubplot”对象没有与初始化函数相关的属性“ set_data”,但是我找不到替代的方法这个。
非常感谢您对此错误或其他明显错误的建议
答案 0 :(得分:0)
您在这里:
import pandas as pd
import numpy as np
import seaborn as sns
import matplotlib.pyplot as plt
import matplotlib.animation as animation
import random
%matplotlib notebook
# Suppose 3 fixed sensors, each with a result every day for 5 days
days = sorted(list(range(5))*3)
channel = (list(range(3)))*5
long = (random.sample(range(10, 20), 3))*5
lat = (random.sample(range(25, 35), 3))*5
colours = ['green', 'yellow', 'orange', 'red', 'brown']
colour = random.choices(colours, k=15)
# create dataframe
data = pd.DataFrame(list(zip(days, channel, long, lat, colour)), columns = ['day', 'sensor', 'x', 'y', 'colour'] )
# print (data)## use this to better understand what is being plotted
# Set up the plot to be animated
# I'm using ax. here, but you could also just use plt.
fig, ax = plt.subplots(figsize=(5,5))
ax.set_xlim(10, 20)
ax.set_xlabel('Longitude',fontsize=20)
ax.set_ylim(25, 35)
ax.set_ylabel('Latitude',fontsize=20)
ax.set_title('Daily changes in pollution levels',fontsize=20)
for i, txt in enumerate(data.sensor):
ax.annotate(txt, xy=(data.x[i], data.y[i]), textcoords='offset points', xytext=(10,10), fontsize=20, weight='bold')
# for convenience: define a function which prepares the data
def get_data(day=0,sensor_id=0):
x = data.loc[(data.day ==day) & (data.sensor ==sensor_id), 'x']
y = data.loc[(data.day ==day) & (data.sensor ==sensor_id), 'y']
col = data.loc[(data.day ==day) & (data.sensor ==sensor_id), 'colour']
return x,y,col
# initialization function
def init():
# plot the first day (day=0) here:
for j in range(3):
x,y,col=get_data(day=0,sensor_id=j)
scat = ax.scatter(x,y,c=col, s=100)
return scat
# animation function
def animate(i):
for j in range(0,3):
x,y,col=get_data(day=i,sensor_id=j)
# print(i,col)## use this to understand "where" we are
scat = ax.scatter(x,y,c=col, s=100)
# return plot object
return scat
# call the animator
# you are iterating over day=i, so you only have 5 frames here
# also you cant use blit=True here
anim = animation.FuncAnimation(fig, animate, init_func=init, frames=5, interval=200,)
plt.show()