Skip to main content
 首页 » 编程设计

python之如何在 matplotlib 中为 basemap 上的散点图制作动画

2024年08月28日30haluo1

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

我怀疑这与我不了解 basemap 的真正是什么有关。我知道在纬度/经度上调用它以将它们投影到 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 

请您参考如下方法:

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

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, 

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