SSMI/S海冰浓度数据:经纬度转xy坐标及冰浓度获取问题
根据经纬度获取哥白尼海冰浓度值的解决方案
问题描述
需要根据给定经纬度(例:lon=-74.7732772827148、lat=-69.3250350952148)获取哥白尼气候变化服务中心卫星海冰浓度数据中的对应值,数据集核心属性如下:
double xc(xc) ; xc:units = "km" ; xc:long_name = "x coordinate of projection (eastings)" ; xc:standard_name = "projection_x_coordinate" ; double yc(yc) ; yc:units = "km" ; yc:long_name = "y coordinate of projection (northings)" ; yc:standard_name = "projection_y_coordinate" ; float lat(yc, xc) ; lat:units = "degrees_north" ; lat:long_name = "latitude coordinate" ; lat:standard_name = "latitude" ; float lon(yc, xc) ; lon:units = "degrees_east" ; lon:long_name = "longitude coordinate" ; lon:standard_name = "longitude" ; int ice_conc(time, yc, xc) ; ice_conc:_FillValue = -32767 ; ice_conc:long_name = "fully filtered concentration of sea ice using atmospheric correction of brightness temperatures and open water filters" ; ice_conc:standard_name = "sea_ice_area_fraction" ; ice_conc:units = "%" ; ice_conc:valid_min = 0 ; ice_conc:valid_max = 10000 ; ice_conc:grid_mapping = "Lambert_Azimuthal_Grid" ; ice_conc:coordinates = "time lat lon" ; ice_conc:ancillary_variables = "total_standard_error status_flag" ; ice_conc:scale_factor = 0.01 ; ice_conc:comment = "this field is the primary sea ice concentration estimate for this climate data record"
由于lat、lon是xc、yc的二维函数,无法直接匹配对应的xc、yc;尝试用pyproj做投影转换后得到的坐标(例:x1=-1586154.04、y1=598565.78)与数据集xc、yc的范围(-5387.5至5387.5)不匹配,现询问是否存在无需投影转换即可直接获取对应海冰浓度值的方法。
可行方案
方法1:直接利用数据集自带的lat/lon数组做空间匹配
数据集已经预先生成了每个(xc,yc)网格点对应的lat和lon二维数组,完全无需投影转换,直接通过空间匹配找到目标经纬度对应的网格点即可,推荐两种实现方式:
用xarray的sel方法(最简方案)
如果数据用xarray打开,可直接调用sel方法结合最近邻匹配快速获取结果:
import xarray as xr # 打开海冰浓度数据集 ds = xr.open_dataset('your_sea_ice_data_file.nc') # 目标经纬度 target_lon = -74.7732772827148 target_lat = -69.3250350952148 # 匹配最近网格点的海冰浓度,自动关联lat/lon坐标 ice_conc_raw = ds.ice_conc.sel(lat=target_lat, lon=target_lon, method='nearest') # 应用scale_factor转换为实际百分比(原始值是放大100倍的整数) ice_conc_value = ice_conc_raw * ds.ice_conc.scale_factor print(f"海冰浓度值:{ice_conc_value.values}%")
用scipy的KDTree做空间索引(适合批量查询)
如果需要批量处理多个经纬度点,用KDTree构建空间索引能大幅提升查询效率:
import numpy as np from scipy.spatial import KDTree import xarray as xr ds = xr.open_dataset('your_sea_ice_data_file.nc') # 将二维lat/lon数组展开为一维点集 lat_flat = ds.lat.values.flatten() lon_flat = ds.lon.values.flatten() grid_points = np.column_stack((lon_flat, lat_flat)) # 构建KDTree索引 tree = KDTree(grid_points) # 单个目标点(批量可传入二维数组) target_point = np.array([[-74.7732772827148, -69.3250350952148]]) # 查询最近邻的距离和索引 _, nearest_idx = tree.query(target_point, k=1) # 将一维索引还原为二维(yc, xc)索引 yc_idx, xc_idx = np.unravel_index(nearest_idx, ds.lat.shape) # 获取海冰浓度并转换为百分比 ice_conc_value = ds.ice_conc.values[:, yc_idx, xc_idx] * ds.ice_conc.scale_factor
方法2:修正投影转换参数(如果必须用投影方法)
之前转换结果与数据集xc/yc范围不匹配的原因有两个:
- 转换结果单位是米,而数据集xc/yc单位是千米,需除以1000;
transform参数顺序错误(应该是(lon, lat)而非(lat, lon))。
修正后的投影转换代码:
from pyproj import Proj, transform import numpy as np # 匹配数据集的南极Lambert方位等角投影参数 lambert_proj = {'proj': 'laea', 'lat_0': -90, 'lon_0': 0, 'ellps': 'WGS84', 'datum': 'WGS84', 'units': 'm'} in_proj = Proj('epsg:4326') # WGS84经纬度坐标系 out_proj = Proj(lambert_proj) # 注意参数顺序:(lon, lat) x_m, y_m = transform(in_proj, out_proj, -74.7732772827148, -69.3250350952148) # 转换为千米,匹配数据集xc/yc单位 xc = x_m / 1000 yc = y_m / 1000 print(f"匹配数据集的xc: {xc:.2f}, yc: {yc:.2f}") # 结果将落在-5387.5~5387.5范围内
内容的提问来源于stack exchange,提问作者13johs
相关产品推荐
相关产品推荐

