【前言】最近在編寫一個氣象應用程序,用來顯示某一時刻某一地區的氣溫等值線和風場,程序主要用到了第三方庫matplotlib及Basemap。在編寫的過程中發現,如果不進行擦除操作直接繪制新的等值線或風場,新的等值線(風場)會與原來的等值線(風場)疊加在一起,而繪制的等值線及風場沒有單獨的remove方法,所以如果想要擦除已經繪制的等值線就要將地圖重新投影一遍,如果地圖投影精度高一點,整個投影過程就會特別漫長。通過對等值線及風場的返回結果進行研究,我找到了一個不必重新投影地圖就可將等值線及風場擦除的方法。
一、matplotlib及Basemap
matplotlib是Python常用的數據繪制包。它基於numpy的數組運算功能,可以輕易的畫出各種統計圖形,如散點圖,條行圖,餅圖,等值線圖等。
Basemap是Matplotlib的一個子包,負責地圖繪制。在數據可視化過程中,我們可以將數據在地圖上畫出來。
利用matplotlib及Basemap畫圖的基本步驟是:
- 創建一個figure實例
- 在figure里創建Axes容器實例
- 在Axes容器內創建Basemap實例進行地圖投影
- 調用Basemap實例的contour及barbs方法進行在地圖上繪圖
二、不進行擦除操作直接繪制新的等值線或風場效果演示
為了方便演示,數據為我自己手中的數據,其中values,x1,y1
為等值線的數據及坐標,huvalues,hvvalues,x2,y2
為風場的數據及坐標,數據的格式及獲得方法就不做過多解釋
1. 繪制地圖投影
import matplotlib.pyplot as plt
from mpl_toolkits.basemap import Basemap
fig = plt.figure()
ax = fig.add_axes([0,0,1,1])
m = Basemap(projection= 'laea', lon_0= 90, lat_0= 40, width= 11000000, \
height= 8000000,resolution='l',ax=ax)
m.drawcoastlines(color='tan')
plt.show()
我們將得到下圖演示的結果
2. 繪制等值線
import matplotlib.pyplot as plt
from mpl_toolkits.basemap import Basemap
fig = plt.figure()
ax = fig.add_axes([0,0,1,1])
m = Basemap(projection= 'laea', lon_0= 90, lat_0= 40, width= 11000000, \
height= 8000000,resolution='l',ax=ax)
m.drawcoastlines(color='tan')
c= m.contour(x1,y1,values,15,linewidths=1.5)
plt.show()
得到結果如下:
3. 繼續繪制風場
import matplotlib.pyplot as plt
from mpl_toolkits.basemap import Basemap
fig = plt.figure()
ax = fig.add_axes([0,0,1,1])
m = Basemap(projection= 'laea', lon_0= 90, lat_0= 40, width= 11000000, \
height= 8000000,resolution='l',ax=ax)
m.drawcoastlines(color='tan')
c= m.contour(x1,y1,values,15,linewidths=1.5)
b= m.barbs(x2,y2,huvalues*2.5,hvvalues*2.5)
plt.show()
得到結果如下:
由此我們可以看出,如果在繪制新的等值線或者風場前不進行擦除操作,所有的圖像都會疊加在一起
三、通過重新進行地圖投影進行擦除操作
1. 繪制地圖投影
import matplotlib.pyplot as plt
from mpl_toolkits.basemap import Basemap
fig = plt.figure()
ax = fig.add_axes([0,0,1,1])
m = Basemap(projection= 'laea', lon_0= 90, lat_0= 40, width= 11000000, \
height= 8000000,resolution='l',ax=ax)
m.drawcoastlines(color='tan')
plt.show()
我們將得到下圖演示的結果
2. 繪制等值線
import matplotlib.pyplot as plt
from mpl_toolkits.basemap import Basemap
fig = plt.figure()
ax = fig.add_axes([0,0,1,1])
m = Basemap(projection= 'laea', lon_0= 90, lat_0= 40, width= 11000000, \
height= 8000000,resolution='l',ax=ax)
m.drawcoastlines(color='tan')
c= m.contour(x1,y1,values,15,linewidths=1.5)
plt.show()
得到結果如下:
3. 擦除axes重新進行地圖投影
import matplotlib.pyplot as plt
from mpl_toolkits.basemap import Basemap
fig = plt.figure()
ax = fig.add_axes([0,0,1,1])
m = Basemap(projection= 'laea', lon_0= 90, lat_0= 40, width= 11000000, \
height= 8000000,resolution='l',ax=ax)
m.drawcoastlines(color='tan')
x1,y1=m(lon,lat)
c= m.contour(x1,y1,values,15,linewidths=1.5)
ax.clear()
m = Basemap(projection= 'laea', lon_0= 90, lat_0= 40, width= 11000000, \
height= 8000000,resolution='l',ax=ax)
m.drawcoastlines(color='tan')
plt.show()
得到下圖結果:
4. 繪制風場
import matplotlib.pyplot as plt
from mpl_toolkits.basemap import Basemap
fig = plt.figure()
ax = fig.add_axes([0,0,1,1])
m = Basemap(projection= 'laea', lon_0= 90, lat_0= 40, width= 11000000, \
height= 8000000,resolution='l',ax=ax)
m.drawcoastlines(color='tan')
c= m.contour(x1,y1,values,15,linewidths=1.5)
ax.clear()
m = Basemap(projection= 'laea', lon_0= 90, lat_0= 40, width= 11000000, \
height= 8000000,resolution='l',ax=ax)
m.drawcoastlines(color='tan')
x2,y2= m(hulon,hulat)
b= m.barbs(x2,y2,huvalues*2.5,hvvalues*2.5)
plt.show()
得到結果如下:
此方法雖然可以達到預期的效果,但是我們的地圖投影並未做過改變,重新進行地圖投影毫無意義,而且還會占用系統不必要的資源
四、對等值線實例及風場實例進行研究
1. 等值線
通過dir()
命令我們可以查看創建的等值線實例c
的屬性方法
print(dir(c))
['_A', '__class__', '__delattr__', '__dict__', '__dir__', '__doc__', '__eq__', '__format__', '__ge__', '__getattribute__',
'__getstate__', '__gt__', '__hash__', '__init__', '__le__', '__lt__', '__module__', '__ne__', '__new__', '__reduce__',
'__reduce_ex__', '__repr__', '__setattr__', '__sizeof__', '__str__', '__subclasshook__', '__weakref__', '_add_label',
'_auto', '_autolev', '_check_xyz', '_contour_args', '_contour_generator', '_contour_level_args', '_corner_mask',
'_get_allsegs_and_allkinds', '_get_label_clabeltext', '_get_label_text', '_get_lowers_and_uppers', '_initialize_x_y',
'_levels', '_make_paths', '_process_args', '_process_colors', '_process_levels', '_process_linestyles', '_process_linewidths',
'_transform', 'add_checker', 'add_label', 'add_label_clabeltext', 'add_label_near', 'allkinds', 'allsegs', 'alpha', 'antialiased',
'autoscale', 'autoscale_None', 'ax', 'calc_label_rot_and_inline', 'callbacksSM', 'changed', 'check_update', 'clabel', 'cmap',
'collections', 'colorbar', 'colors', 'contour_doc', 'cvalues', 'extend', 'extent', 'filled', 'find_nearest_contour', 'get_alpha',
'get_array', 'get_clim', 'get_cmap', 'get_label_coords', 'get_label_width', 'get_real_label_width', 'get_text', 'get_transform',
'hatches', 'labelCValues', 'labelTexts', 'labels', 'layers', 'legend_elements', 'levels', 'linestyles', 'linewidths', 'locate_label',
'locator', 'logscale', 'monochrome', 'nchunk', 'norm', 'origin', 'pop_label', 'print_label', 'set_alpha', 'set_array', 'set_clim',
'set_cmap', 'set_label_props', 'set_norm', 'tcolors', 'tlinewidths', 'to_rgba', 'too_close', 'update_dict', 'vmax', 'vmin',
'zmax', 'zmin']
通過查看,發現在c
的屬性方法中並沒有remove()
方法,但是我們發現有一個屬性是collections
,這里的collections
如果與Python的集合類相同,它就應該有remove()
方法進刪除,所以繼續通過dir()
命令進行查看
print(dir(c.collections)
['__add__', '__class__', '__contains__', '__delattr__', '__delitem__', '__dict__', '__dir__', '__doc__', '__eq__',
'__format__', '__ge__', '__getattribute__', '__getitem__', '__getstate__', '__gt__', '__hash__', '__iadd__',
'__imul__', '__init__', '__iter__', '__le__', '__len__', '__lt__', '__module__', '__mul__', '__ne__', '__new__',
'__reduce__', '__reduce_ex__', '__repr__', '__reversed__', '__rmul__', '__setattr__', '__setitem__',
'__setstate__', '__sizeof__', '__str__', '__subclasshook__', '__weakref__', 'append', 'clear', 'copy',
'count', 'extend', 'index', 'insert', 'pop', 'remove', 'reverse', 'sort', 'type']
通過查看,發現c.collections
有remove()
方法,所以嘗試用c.collections.remove()
進行刪除,由於remove()
方法一次只能刪除一個元素,所以要用for
循環來進行刪除。
import matplotlib.pyplot as plt
from mpl_toolkits.basemap import Basemap
fig = plt.figure()
ax = fig.add_axes([0,0,1,1])
m = Basemap(projection= 'laea', lon_0= 90, lat_0= 40, width= 11000000, \
height= 8000000,resolution='l',ax=ax)
m.drawcoastlines(color='tan')
c= m.contour(x1,y1,values,15,linewidths=1.5)
for i in c.collections:
i.remove()
plt.show()
得到下圖結果:
由此可見,此方法可行
2. 風場
通過dir()
命令我們可以查看創建的等值線實例b
的屬性方法
print(dir(b))
['__add__', '__class__', '__contains__', '__delattr__', '__dir__', '__doc__', '__eq__', '__format__',
'__ge__', '__getattribute__', '__getitem__', '__getnewargs__', '__gt__', '__hash__', '__init__',
'__iter__', '__le__', '__len__', '__lt__', '__mul__', '__ne__', '__new__', '__reduce__', '__reduce_ex__',
'__repr__', '__rmul__', '__setattr__', '__sizeof__', '__str__', '__subclasshook__', 'count', 'index']
可以發現風場的實例b
沒有remove
方法,也沒有collections
屬性,所以決定先通過type()
方法看看風場實例是什么類型的
print(type(b))
<class 'tuple'>
可以發現風場實例b
是一個元組,所以繼續看它的元素有什么屬性
print(dir(b[0]))
['_A', '__class__', '__delattr__', '__dict__', '__dir__', '__doc__', '__eq__', '__format__', '__ge__', '__getattribute__',
'__getstate__', '__gt__', '__hash__', '__init__', '__le__', '__lt__', '__module__', '__ne__', '__new__', '__reduce__',
'__reduce_ex__', '__repr__', '__setattr__', '__sizeof__', '__str__', '__subclasshook__', '__weakref__', '_agg_filter',
'_alpha', '_animated', '_antialiaseds', '_axes', '_clipon', '_clippath', '_contains', '_edgecolors',
'_edgecolors_original', '_facecolors', '_facecolors_original', '_factor', '_find_tails', '_get_bool',
'_get_value', '_gid', '_hatch', '_is_filled', '_is_stroked', '_label', '_length', '_linestyles', '_linewidths',
'_make_barbs', '_mouseover', '_offset_position', '_offsets', '_oid', '_path_effects', '_paths', '_picker',
'_pickradius', '_pivot', '_prepare_points', '_propobservers', '_rasterized', '_remove_method',
'_set_gc_clip', '_sizes', '_sketch', '_snap', '_stale', '_transOffset', '_transform', '_transformSet',
'_transforms', '_uniform_offsets', '_url', '_urls', '_visible', 'add_callback', 'add_checker', 'aname',
'autoscale', 'autoscale_None', 'axes', 'barb_increments', 'barbs_doc', 'callbacksSM', 'changed',
'check_update', 'clipbox', 'cmap', 'colorbar', 'contains', 'convert_xunits', 'convert_yunits', 'draw',
'eventson', 'figure', 'fill_empty', 'findobj', 'flip', 'format_cursor_data', 'get_agg_filter', 'get_alpha',
'get_animated', 'get_array', 'get_axes', 'get_children', 'get_clim', 'get_clip_box', 'get_clip_on',
'get_clip_path', 'get_cmap', 'get_contains', 'get_cursor_data', 'get_dashes', 'get_datalim',
'get_edgecolor', 'get_edgecolors', 'get_facecolor', 'get_facecolors', 'get_figure', 'get_fill', 'get_gid',
'get_hatch', 'get_label', 'get_linestyle', 'get_linestyles', 'get_linewidth', 'get_linewidths',
'get_offset_position', 'get_offset_transform', 'get_offsets', 'get_path_effects', 'get_paths', 'get_picker',
'get_pickradius', 'get_rasterized', 'get_sizes', 'get_sketch_params', 'get_snap', 'get_transform',
'get_transformed_clip_path_and_affine', 'get_transforms', 'get_url', 'get_urls', 'get_visible',
'get_window_extent', 'get_zorder', 'have_units', 'hitlist', 'is_figure_set', 'is_transform_set',
'mouseover', 'norm', 'pchanged', 'pick', 'pickable', 'properties', 'remove', 'remove_callback',
'rounding', 'set', 'set_UVC', 'set_agg_filter', 'set_alpha', 'set_animated', 'set_antialiased', 'set_antialiaseds',
'set_array', 'set_axes', 'set_clim', 'set_clip_box', 'set_clip_on', 'set_clip_path', 'set_cmap', 'set_color',
'set_contains', 'set_dashes', 'set_edgecolor', 'set_edgecolors', 'set_facecolor', 'set_facecolors', 'set_figure',
'set_gid', 'set_hatch', 'set_label', 'set_linestyle', 'set_linestyles', 'set_linewidth', 'set_linewidths', 'set_lw',
'set_norm', 'set_offset_position', 'set_offsets', 'set_path_effects', 'set_paths', 'set_picker', 'set_pickradius',
'set_rasterized', 'set_sizes', 'set_sketch_params', 'set_snap', 'set_transform', 'set_url', 'set_urls', 'set_verts',
'set_verts_and_codes', 'set_visible', 'set_zorder', 'sizes', 'stale', 'stale_callback', 'to_rgba', 'u', 'update',
'update_dict', 'update_from', 'update_scalarmappable', 'v', 'x', 'y', 'zorder']
可以發現風場實例元組的元素自己就有remove
屬性,所以通過remove
方法嘗試一下可不可以進行風場的刪除
import matplotlib.pyplot as plt
from mpl_toolkits.basemap import Basemap
fig = plt.figure()
ax = fig.add_axes([0,0,1,1])
m = Basemap(projection= 'laea', lon_0= 90, lat_0= 40, width= 11000000, \
height= 8000000,resolution='l',ax=ax)
m.drawcoastlines(color='tan')
b=m.barbs(x2,y2,huvalues*2.5,hvvalues*2.5)
for i in b:
i.remove()
plt.show()
得到下圖結果:
由此可見,此方法可行
五、總結
對於等值線,可以通過等值線實例的collection屬性的remove方法進行刪除已經繪制等值線;
對於風場,可以通過風場實例元組中個元素的remove方法進行刪除已繪制風場;
對於地圖上其他繪圖方法,也可以通過本文的方法進行一步步的嘗試。
本文版權歸作者和博客園共有,歡迎轉載,但未經作者同意必須保留此段聲明,且在文章頁面明顯位置給出原文連接,否則保留追究法律責任的權利。
想觀看Matplotlib教學視頻,了解更多Matplotlib實用技巧可關注
微信公眾賬號: MatplotlibClass
今日頭條號:Matplotlib小講堂