如何在matplotlib中为底图上的散点图设置动画?

时间:2014-01-05 16:12:04

标签: python matplotlib matplotlib-basemap

下面的代码生成一个动画底图,但不完全是我想要的底图:我希望前一帧的散点图消失,但它会在动画的其余部分中持续存在。

我怀疑这与我不理解底图真正的内容有关。我理解在lat / lons上调用它来将它们投影到x / y,但是当我调用event_map.scatter()时,我并不完全了解正在发生的事情。

import random
import os
import numpy as np

import matplotlib.pyplot as plt
from mpl_toolkits.basemap import Basemap
from matplotlib import animation
import pandas as pd
from IPython.display import HTML


# Enables animation display directly in IPython 
#(http://jakevdp.github.io/blog/2013/05/12/embedding-matplotlib-animations/)
from tempfile import NamedTemporaryFile

VIDEO_TAG = """<video controls>
 <source src="data:video/x-m4v;base64,{0}" type="video/mp4">
 Your browser does not support the video tag.
</video>"""

def anim_to_html(anim):
    if not hasattr(anim, '_encoded_video'):
        with NamedTemporaryFile(suffix='.mp4') as f:
            anim.save(f.name, fps=20, extra_args=['-vcodec', 'libx264'])
            video = open(f.name, "rb").read()
        anim._encoded_video = video.encode("base64")

    return VIDEO_TAG.format(anim._encoded_video)

def display_animation(anim):
    plt.close(anim._fig)
    return HTML(anim_to_html(anim))

animation.Animation._repr_html_ = anim_to_html



FRAMES = 20
POINTS_PER_FRAME = 30
LAT_MIN = 40.5
LAT_MAX = 40.95
LON_MIN = -74.15
LON_MAX = -73.85
FIGSIZE = (10,10)
MAP_BACKGROUND = '.95'
MARKERSIZE = 20

#Make Sample Data
data_frames = {}
for i in range(FRAMES):
    lats = [random.uniform(LAT_MIN, LAT_MAX) for x in range(POINTS_PER_FRAME)]
    lons = [random.uniform(LON_MIN, LON_MAX) for x in range(POINTS_PER_FRAME)]
    data_frames[i] = pd.DataFrame({'lat':lats, 'lon':lons})    


class AnimatedMap(object):
    """ An animated scatter plot over a basemap"""
    def __init__(self, data_frames):
        self.dfs = data_frames
        self.fig = plt.figure(figsize=FIGSIZE)
        self.event_map = Basemap(projection='merc', 
                resolution='i', area_thresh=1.0, # Medium resolution
                lat_0 = (LAT_MIN + LAT_MAX)/2, lon_0=(LON_MIN + LON_MAX)/2, # Map center 
                llcrnrlon=LON_MIN, llcrnrlat=LAT_MIN, # Lower left corner
                urcrnrlon=LON_MAX, urcrnrlat=LAT_MAX) # Upper right corner 
        self.ani = animation.FuncAnimation(self.fig, self.update, frames=FRAMES, interval=1000, 
                                           init_func=self.setup_plot, blit=True,
                                           repeat=False)

    def setup_plot(self):
        self.event_map.drawcoastlines() 
        self.event_map.drawcounties()
        self.event_map.fillcontinents(color=MAP_BACKGROUND) # Light gray
        self.event_map.drawmapboundary()
        self.scat = self.event_map.scatter(x = [], y=[], s=MARKERSIZE,marker='o', zorder=10) 
        return self.scat

    def project_lat_lons(self, i):
        df = data_frames[i]
        x, y = self.event_map(df.lon.values, df.lat.values)
        x_y = pd.DataFrame({'x': x, 'y': y}, index=df.index)
        df = df.join(x_y)
        return df

    def update(self, i):
        """Update the scatter plot."""
        df = self.project_lat_lons(i)
        self.scat = self.event_map.scatter(x = df.x.values, y=df.y.values,  marker='o', zorder=10)  
        return self.scat,


s = AnimatedMap(data_frames)
s.ani

1 个答案:

答案 0 :(得分:3)

看起来你只是在每次更新时添加一个新的散点图。您应该做的是在每次更新时更改现有路径集合中的数据。尝试一下

的内容
def update(self, i):
    """Update the scatter plot."""
    df = self.project_lat_lons(i)
    new_offsets = np.vstack([df.x.values, df.y.values]).T
    self.scat.set_offsets(new_offsets)
    return self.scat,

请注意,我没有对此进行测试。