首页 > Python资料 博客日记
【python由站点数据插值到网格数据方法对比】
2024-08-01 12:00:05Python资料围观59次
文章【python由站点数据插值到网格数据方法对比】分享给大家,欢迎收藏Python资料网,专注分享技术知识
1、前言
- 气象海洋中空间数据类型有站点数据、格点数据。
- 站点数据空间分布不连续,不利于进行时空分析;有时需要将站点数据插值到网格中。
- 本文基于一个散点数据对比了griddata、IDW、krige、rbf的插值结果。
- interp2d插值,地理数据中的分辨率转换
2、结果对比
2.1 原始散点站位图
- 原始散点站位如下:
2.2 griddata插值
from scipy.interpolate import griddata
lat = df_filter['Lat']
lon = df_filter['Lon']
VIS_Min = df_filter['VIS_Min']
olon = np.linspace(lon.min(), lon.max(), 40)
olat = np.linspace(lat.min(), lat.max(), 40)
olon, olat = np.meshgrid(olon, olat)
VIS_Min_grd=griddata((lon,lat),VIS_Min,(olon, olat),method='linear')
plt.figure(figsize=(8,6))
plt.pcolormesh(olon, olat, VIS_Min_grd)
plt.scatter(lon, lat, s=50, c=VIS_Min, cmap='viridis',edgecolors='k')
- 可视化代码
import os
import numpy as np
import matplotlib.pyplot as plt
import matplotlib.colors as mcolors
import matplotlib as mpl
import cartopy.crs as ccrs
import cartopy.io.shapereader as shpreader
from mpl_toolkits.axes_grid1.inset_locator import inset_axes
from matplotlib.colors import LinearSegmentedColormap
import regionmask
import geopandas as gpd
import warnings
warnings.filterwarnings("ignore")
import matplotlib.ticker as ticker
extents = [115.6, 117.2, 39.7, 40.8]
crs = ccrs.PlateCarree()
fig = plt.figure(figsize=(12, 6))
ax = fig.add_subplot(111, projection=crs)
ax.set_extent(extents, crs)
prov_reader = shpreader.Reader(r'.\bou2_4p.shp')
nineline_reader = shpreader.Reader(r'.\九段线.shp')
ax.add_geometries(prov_reader.geometries(), crs, edgecolor='gray', facecolor='none', lw=1)
ax.add_geometries(nineline_reader.geometries(), crs, edgecolor='gray', facecolor='none', lw=1)
ax.set_xticks(np.arange(extents[0], extents[1] + 0.3, 0.3))
ax.set_yticks(np.arange(extents[2], extents[3] + 0.2, 0.2))
plt.tick_params(axis='both', which='major', labelsize=18)
norm = mcolors.Normalize(vmin=0, vmax=np.round(VIS_Min.max()))
cmap_jet = plt.cm.jet
cmap_gray = plt.cm.gray
gray = cmap_gray(np.linspace(0, 1, 9))
colors = np.vstack((gray[8], cmap_jet(np.linspace(0, 1, 9))))
cmaps = LinearSegmentedColormap.from_list('Combined', colors, N=64)
map = plt.pcolormesh(olon, olat, VIS_Min_grd, cmap=cmaps)
plt.scatter(lon, lat, s=50, c=VIS_Min, cmap=cmaps,edgecolors='k',norm=norm)
cb_ax = inset_axes(ax, width="3%", height="100%", loc='lower left', bbox_to_anchor=(1.01, 0., 1, 1),
bbox_transform=ax.transAxes, borderpad=0)
cbar = plt.colorbar(mpl.cm.ScalarMappable(norm=norm, cmap=cmaps), cax=cb_ax, ax=map)
cbar.ax.set_title('能见度', size=18, fontname='SimHei', pad=10)
cbar.ax.tick_params(labelsize=15)
ax.set_xlabel('Lon(°E)', fontsize=18)
ax.set_ylabel('Lat(°N)', fontsize=18)
ax.set_title('原始散点站位', size=18, fontname='SimHei', pad=10)
- 可视化结果
2.3 krige插值
- 插值核心代码
from pykrige.ok import OrdinaryKriging
lat = df_filter['Lat']
lon = df_filter['Lon']
VIS_Min = df_filter['VIS_Min']
olon = np.linspace(lon.min(), lon.max(), 40)
olat = np.linspace(lat.min(), lat.max(), 40)
Krin=OrdinaryKriging(lon,lat,VIS_Min,variogram_model='gaussian',
coordinates_type="geographic",
nlags=1,)
data2,ssl=Krin.execute('grid',olon,olat)
olon, olat = np.meshgrid(olon, olat)
plt.figure(figsize=(8,6))
plt.pcolormesh(olon, olat, data2)
plt.scatter(lon, lat, s=50, c=VIS_Min, cmap='viridis',edgecolors='k')
- 插值结果
2.4 RBF插值
- 插值核心代码
from scipy.interpolate import Rbf
lat = df_filter['Lat']
lon = df_filter['Lon']
VIS_Min = df_filter['VIS_Min']
olon = np.linspace(lon.min(), lon.max(), 40)
olat = np.linspace(lat.min(), lat.max(), 40)
olon, olat = np.meshgrid(olon, olat)
func1=Rbf(lon,lat,VIS_Min,function='linear')
VIS_Min_rbf=func1(olon,olat)
plt.figure(figsize=(8,6))
plt.pcolormesh(olon, olat, VIS_Min_rbf)
plt.scatter(lon, lat, s=50, c=VIS_Min, cmap='viridis',edgecolors='k')
- 插值结果
2.5 IDW插值
- 插值核心代码
from math import radians, sin, cos, sqrt, asin
import numpy as np
# degree to km (Haversine method)
def haversine(lon1, lat1, lon2, lat2):
R = 6372.8 # Earth radius in kilometers
dLon = radians(lon2 - lon1)
dLat = radians(lat2 - lat1)
lat1 = radians(lat1)
lat2 = radians(lat2)
a = sin(dLat/2)**2 + cos(lat1)*cos(lat2)*sin(dLon/2)**2
c = 2*asin(sqrt(a))
d = R * c
return d
def IDW(x, y, z, xi, yi):
lstxyzi = []
for p in range(len(xi)):
lstdist = []
for s in range(len(x)):
d = (haversine(x[s], y[s], xi[p], yi[p]))
lstdist.append(d)
sumsup = list((1 / np.power(lstdist, 2)))
suminf = np.sum(sumsup)
sumsup = np.sum(np.array(sumsup) * np.array(z))
u = sumsup / suminf
xyzi = [xi[p], yi[p], u]
lstxyzi.append(xyzi)
return(lstxyzi)
lat = df_filter['Lat']
lon = df_filter['Lon']
VIS_Min = df_filter['VIS_Min']
olon = np.linspace(lon.min(), lon.max(), 40)
olat = np.linspace(lat.min(), lat.max(), 40)
olon, olat = np.meshgrid(olon, olat)
VIS_Min_idw=IDW(lon,lat,VIS_Min,olon.flatten(), olat.flatten())
VIS_Min_idw= np.array(VIS_Min_idw)[:,2].reshape(olon.shape)
plt.figure(figsize=(8,6))
plt.pcolormesh(olon, olat, VIS_Min_idw)
plt.scatter(lon, lat, s=50, c=VIS_Min, cmap='viridis',edgecolors='k')
- 矩阵运算
import numpy as np
def haversine(lon1, lat1, lon2, lat2):
R = 6372.8 # Earth radius in kilometers
dLon = np.radians(lon2 - lon1)
dLat = np.radians(lat2 - lat1)
lat1 = np.radians(lat1)
lat2 = np.radians(lat2)
a = np.sin(dLat / 2) ** 2 + np.cos(lat1) * np.cos(lat2) * np.sin(dLon / 2) ** 2
c = 2 * np.arcsin(np.sqrt(a))
d = R * c
return d
def IDW(x, y, z, xi, yi):
xi, yi = np.meshgrid(xi, yi) # Create grid
xi = xi.ravel()
yi = yi.ravel()
dists = haversine(np.tile(x, (len(xi), 1)).T, np.tile(y, (len(yi), 1)).T, xi, yi)
weights = 1 / dists ** 2
weights[np.isinf(weights)] = 1e12 # Handle division by zero
weighted_sum = np.sum(weights * z[:, None], axis=0)
sum_of_weights = np.sum(weights, axis=0)
u = weighted_sum / sum_of_weights
result = np.column_stack((xi, yi, u))
return result
# 示例数据
x = np.array([0, 1, 2, 3, 4])
y = np.array([0, 1, 2, 3, 4])
z = np.array([1, 2, 3, 4, 5])
xi = np.linspace(0, 4, 10)
yi = np.linspace(0, 4, 10)
# 进行IDW插值
interpolated_data = IDW(x, y, z, xi, yi)
print(interpolated_data[:,2])
- 插值结果
3、总结
- 插值范围上,除了griddata以外的其它插值方法,都可以插值到站点以外的区域;
- 插值效果上,从本案例的结果上看,我认为反距离权重IDW结果最好,之后为RBF,其次是克里金。
4、其它
- 在数据插值过程中,发现了MetPy库下的inverse_distance_to_grid插值函数。用于执行基于反距离权重(Inverse Distance Weighting, IDW)的插值算法,常用于气象学和其他领域的空间数据分析。这个函数允许你将一系列离散观测点的数据插值到一个网格上,从而生成连续的空间场。
- 使用上述数据,调整了相关参数,做了插值,结果并不理想。
from metpy.interpolate import inverse_distance_to_grid
data = inverse_distance_to_grid(lon,lat,VIS_Min, olon, olat, r=0.5)
plt.figure(figsize=(8,6))
plt.pcolormesh(olon, olat, data)
plt.scatter(lon, lat, s=50, c=VIS_Min, cmap='viridis',edgecolors='k')
5、国家站能见度插值结果对比
- 基于全国2000多各国家站逐小时能见度结果进行插值结果对比。
- 对比方法包括griddata、rbf、IDW
- 插值效率:griddata > rbf > IDW
- 插值效果:rbf > griddata > IDW
版权声明:本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若内容造成侵权/违法违规/事实不符,请联系邮箱:jacktools123@163.com进行投诉反馈,一经查实,立即删除!
标签:
相关文章
最新发布
- 【Python】selenium安装+Microsoft Edge驱动器下载配置流程
- Python 中自动打开网页并点击[自动化脚本],Selenium
- Anaconda基础使用
- 【Python】成功解决 TypeError: ‘<‘ not supported between instances of ‘str’ and ‘int’
- manim边学边做--三维的点和线
- CPython是最常用的Python解释器之一,也是Python官方实现。它是用C语言编写的,旨在提供一个高效且易于使用的Python解释器。
- Anaconda安装配置Jupyter(2024最新版)
- Python中读取Excel最快的几种方法!
- Python某城市美食商家爬虫数据可视化分析和推荐查询系统毕业设计论文开题报告
- 如何使用 Python 批量检测和转换 JSONL 文件编码为 UTF-8
点击排行
- 版本匹配指南:Numpy版本和Python版本的对应关系
- 版本匹配指南:PyTorch版本、torchvision 版本和Python版本的对应关系
- Python 可视化 web 神器:streamlit、Gradio、dash、nicegui;低代码 Python Web 框架:PyWebIO
- 相关性分析——Pearson相关系数+热力图(附data和Python完整代码)
- Python与PyTorch的版本对应
- Anaconda版本和Python版本对应关系(持续更新...)
- Python pyinstaller打包exe最完整教程
- Could not build wheels for llama-cpp-python, which is required to install pyproject.toml-based proj