Python 如何将等高线图叠加到底图上
这是我几个月前提出的一个问题,我仍在努力寻找解决方案。我的代码会同时给我一个底图和一个等高线图(但打印到文件中只会得到等高线图),但我希望它们叠加在一起。最好的解决方案是这里的解决方案,但这并没有说明如何引入数据,而且当您在网上从头开始学习时,这是很困难的。 我希望这个解决方案能像修改一行代码一样简单,并且有人能帮上忙。 我的代码 我得到的情节是这样的 还有我的数据Python 如何将等高线图叠加到底图上,python,matplotlib,pandas,gis,matplotlib-basemap,Python,Matplotlib,Pandas,Gis,Matplotlib Basemap,这是我几个月前提出的一个问题,我仍在努力寻找解决方案。我的代码会同时给我一个底图和一个等高线图(但打印到文件中只会得到等高线图),但我希望它们叠加在一起。最好的解决方案是这里的解决方案,但这并没有说明如何引入数据,而且当您在网上从头开始学习时,这是很困难的。 我希望这个解决方案能像修改一行代码一样简单,并且有人能帮上忙。 我的代码 我得到的情节是这样的 还有我的数据 32.6 -13.6 41 27.1 -16.9 43 32.7 -10.2 46 24.2 -13.6
32.6 -13.6 41
27.1 -16.9 43
32.7 -10.2 46
24.2 -13.6 33
28.5 -14.4 43
28.1 -12.6 33
27.9 -15.8 46
24.8 -14.8 44
31.1 -10.2 35
25.9 -13.5 24
29.1 -9.8 10
25.8 -17.8 39
33.2 -12.3 44
28.3 -15.4 46
27.6 -16.1 47
28.9 -11.1 31
31.3 -8.9 39
31.9 -13.3 45
23.1 -15.3 31
31.4 -11.9 39
27.1 -15.0 42
24.4 -11.8 15
28.6 -13.0 39
31.3 -14.3 44
23.3 -16.1 39
30.2 -13.2 38
24.3 -17.5 32
26.4 -12.2 23
23.1 -13.5 27
我并没有在这里安装所有的东西来运行您的代码,但是您应该尝试打印到您创建的basemap
m
,如下所示:
# fig = plt.figure(figsize=(10,8)) # omit this at line 28
(...)
m.contourf(xi, yi, zi)
m.scatter(data.Lon, data.Lat, c=data.Z, s=100,
vmin=zi.min(), vmax=zi.max())
(如果这不起作用,请告诉我)你就快到了,但是底图可能是喜怒无常的,你必须管理绘图/地图细节的z顺序。此外,在使用basemap绘制投影坐标之前,必须将lon/lat坐标转换为地图投影坐标 这是一个完整的解决方案,它给出了以下输出。YMMV,为了使整个东西更清晰,我改变了一些颜色和线宽。我还通过标准化的“平均”值(
data['Z']
)缩放了分散点的大小–如果您喜欢恒定的大小(它看起来像是最大的标记),您可以简单地将其删除并替换,例如50
)
如有可能,还请说明产生平均值的降雨量单位和测量持续时间:
import numpy as np
import pandas as pd
from matplotlib.mlab import griddata
from mpl_toolkits.basemap import Basemap
import matplotlib.pyplot as plt
from matplotlib.colors import Normalize
%matplotlib inline
# set up plot
plt.clf()
fig = plt.figure(figsize=(10, 8))
ax = fig.add_subplot(111, axisbg='w', frame_on=False)
# grab data
data = pd.read_csv('../../data/meansr.txt', delim_whitespace=True)
norm = Normalize()
# define map extent
lllon = 21
lllat = -18
urlon = 34
urlat = -8
# Set up Basemap instance
m = Basemap(
projection = 'merc',
llcrnrlon = lllon, llcrnrlat = lllat, urcrnrlon = urlon, urcrnrlat = urlat,
resolution='h')
# transform lon / lat coordinates to map projection
data['projected_lon'], data['projected_lat'] = m(*(data.Lon.values, data.Lat.values))
# grid data
numcols, numrows = 1000, 1000
xi = np.linspace(data['projected_lon'].min(), data['projected_lon'].max(), numcols)
yi = np.linspace(data['projected_lat'].min(), data['projected_lat'].max(), numrows)
xi, yi = np.meshgrid(xi, yi)
# interpolate
x, y, z = data['projected_lon'].values, data['projected_lat'].values, data.Z.values
zi = griddata(x, y, z, xi, yi)
# draw map details
m.drawmapboundary(fill_color = 'white')
m.fillcontinents(color='#C0C0C0', lake_color='#7093DB')
m.drawcountries(
linewidth=.75, linestyle='solid', color='#000073',
antialiased=True,
ax=ax, zorder=3)
m.drawparallels(
np.arange(lllat, urlat, 2.),
color = 'black', linewidth = 0.5,
labels=[True, False, False, False])
m.drawmeridians(
np.arange(lllon, urlon, 2.),
color = '0.25', linewidth = 0.5,
labels=[False, False, False, True])
# contour plot
con = m.contourf(xi, yi, zi, zorder=4, alpha=0.6, cmap='RdPu')
# scatter plot
m.scatter(
data['projected_lon'],
data['projected_lat'],
color='#545454',
edgecolor='#ffffff',
alpha=.75,
s=50 * norm(data['Z']),
cmap='RdPu',
ax=ax,
vmin=zi.min(), vmax=zi.max(), zorder=4)
# add colour bar and title
# add colour bar, title, and scale
cbar = plt.colorbar(conf, orientation='horizontal', fraction=.057, pad=0.05)
cbar.set_label("Mean Rainfall - mm")
m.drawmapscale(
24., -9., 28., -13,
100,
units='km', fontsize=10,
yoffset=None,
barstyle='fancy', labelstyle='simple',
fillcolor1='w', fillcolor2='#000000',
fontcolor='#000000',
zorder=5)
plt.title("Mean Rainfall")
plt.savefig("rainfall.png", format="png", dpi=300, transparent=True)
plt.show()
使用matplotlib的griddata
方法很方便,但也可能很慢。作为替代方案,您可以使用scipy的方法,这些方法更快、更灵活:
from scipy.interpolate import griddata as gd
zi = gd(
(data[['projected_lon', 'projected_lat']]),
data.Z.values,
(xi, yi),
method='linear')
如果使用scipy的griddata
方法,还必须确定哪种方法(最接近的,线性的
,立方的
)给出最佳结果图
我应该补充一点,上面演示和讨论的插值方法是最简单的,并且不一定适用于降雨数据的插值。对水文和水文建模中使用的有效方法和注意事项进行了概述。这些(可能使用Scipy)的实现留作练习&c.显然,您会得到两个图形,因为m
是调用每个地图绘制命令的上下文,在使用plt
基于绘图命令绘制当前活动图形之后。为什么要使用R标记?你在Python中的设置似乎很好。你能分享meansr.txt来运行你的代码吗?用你发送的代码片段替换我的绘图函数来绘制没有等高线或散点图的地图。感谢所有花时间阅读我的代码(上面)的人,以及帮助我使代码正常工作的人(六个月前),特别是@urschrei。从那以后,我一直想知道python中是否有外推。我知道外推可能会得出奇怪的结果,但我在文档中没有看到任何东西。是否可以进行外推以至少填充地图?我很惊讶这个“简单”问题没有答案:python中是否有外推命令?@ziloremmba您可以使用,例如,scypy.rbf
模块为一组数据创建rbf内插器。然后,您可以在远离原始数据集的地方进行插值(即外推),但要检查结果,因为距离越远,错误越大。还有,看看其他插值器,不仅仅是RBF(还有克里格法,但我想不是天生的scipy
。谢谢@heltonbiker,我会试试。非常感谢你宝贵的时间@urschrei。这也将为我提供学习材料。我已经为此工作了近一年。我已经记下了你提出的所有建议。顺便问一句,YMMV是什么意思?我从ith R。我能够在R中的地图上得到等高线,但我知道人们无法推断(填充该区域)在r中。虽然我还没有外推,但我认为我可以很高兴地与python一起生活。非常感谢所有善良和乐于助人的人。@ziloremmba YMMV的意思是“你的里程可能会有所不同”——你可能会对我所做的颜色贴图和线宽选择有不同的感觉,你应该可以自由地尝试这些。祝你好运!@AndreAraujo It's只有原始数据,保存为txt文件,标题行为:Lon Lat Values
。该文件以空格分隔。
from scipy.interpolate import griddata as gd
zi = gd(
(data[['projected_lon', 'projected_lat']]),
data.Z.values,
(xi, yi),
method='linear')