import numpy as np
from netCDF4 import Dataset
import pickle
import glob
import pandas as pd
import geopandas as gpd
def bring(file_name,var_name,yr0):
x=Dataset(file_name)
lon=x.variables['lon'][:]
lat=x.variables['lat'][:]
lon_min, lon_max, lat_min, lat_max = 96, 122, 31, 42
lon_idx = np.where((lon >= lon_min) & (lon <= lon_max))[0]
lat_idx = np.where((lat >= lat_min) & (lat <= lat_max))[0]
lon = lon[lon_idx]
lat = lat[lat_idx]
var = x.variables[var_name][:,lat_idx,lon_idx]
#convert time to helpful datetime index
dates=np.array(str(yr0) + '-01-01',dtype=np.datetime64)
dts=np.linspace(0,len(x.variables['time'][:])-1,len(x.variables['time'][:]))
dates=dates+dts.astype(int)
dates=pd.DatetimeIndex(dates)
return(lon,lat,var,dates)
folder='D:\\shuju\\'
stem='China_1km_prep_*'
files=glob.glob(folder+stem)
#number of days exceeding these thresholds per year (wet days at lowest)
for f in range(len(files)):
file_name=files[f]
var_name='prep'
yr0 = int(file_name.split('prep_')[1][0:4])
[lon,lat,pr,dates]=bring(file_name,var_name,yr0)
print(pr.ndim)
print(pr.shape)
#calculate number of wet days, and amount of rainon wet days, and amount of rain in excess of threshold, on a sequence of absolute thresholds
intermed=np.sum(pr,axis=0)
intermed = np.expand_dims(intermed, axis=0)
#append these wet days measures to the previous years values
if f==0:
Pt=intermed
elif f==1:
Pt=np.stack((Pt,intermed),axis=0)
else:
Pt=np.concatenate((Pt,np.expand_dims(intermed,axis=0)),axis=0)
del intermed
del pr
print('done year ' + str(int(file_name.split('prep_')[1][0:4])))
mask = gpd.read_file('D:\\shuju\\shp\\liujingdexian\\LYDX.gpkg',layer=0)
isos=pd.unique(mask.OBJECTID_1)
for i in range(len(isos)):
measure = np.zeros((1, 1))
# load region specific coordinates and weights
crds_file = str(18) + '_crds_wghts.pkl'
if len(glob.glob(crds_file)) != 0:
with open(crds_file, 'rb') as f:
[loni_c, lati_c, weights_c] = pickle.load(f)
Z = Pt[:, lati_c, loni_c]
# apply coordinates and weightings to obtain region specific measures
if len(weights_c) != 0:
measure[0, :] = np.dot(Z, np.array(weights_c)) / sum(weights_c)
else:
measure[0, :] = np.nan
#save measures
np.save('secondary_data/measures/precip/Pt_' + str(i) + '.npy',measure)
该回答通过自己思路及引用到GPTᴼᴾᴱᴺᴬᴵ搜索,得到内容具体如下。
在进行格网数据汇总时,报错坐标超出界限,这通常是因为在选择范围时,选择了超出数据范围的坐标。需要检查选择范围是否正确,并根据数据的实际范围进行调整。
具体来说,可以在以下代码中检查选择范围:
lon_min, lon_max, lat_min, lat_max = 96, 122, 31, 42
lon_idx = np.where((lon >= lon_min) & (lon <= lon_max))[0]
lat_idx = np.where((lat >= lat_min) & (lat <= lat_max))[0]
在这里,lon_min, lon_max, lat_min, lat_max 是选择的经度和纬度范围。如果超出了数据范围,则需要进行相应的调整。
另外,需要注意的是,在进行坐标选择时,需要保证选择的坐标是单调递增或递减的。如果选择的坐标不是单调的,可能会导致数据读取错误。
以下是修改后的完整代码:
import numpy as np
from netCDF4 import Dataset
import pickle
import glob
import pandas as pd
import geopandas as gpd
def bring(file_name,var_name,yr0):
x=Dataset(file_name)
lon=x.variables['lon'][:]
lat=x.variables['lat'][:]
lon_min, lon_max, lat_min, lat_max = 96, 122, 31, 42
lon_idx = np.where((lon >= lon_min) & (lon <= lon_max))[0]
lat_idx = np.where((lat >= lat_min) & (lat <= lat_max))[0]
lon = lon[lon_idx]
lat = lat[lat_idx]
var = x.variables[var_name][:,lat_idx,lon_idx]
#convert time to helpful datetime index
dates=np.array(str(yr0) + '-01-01',dtype=np.datetime64)
dts=np.linspace(0,len(x.variables['time'][:])-1,len(x.variables['time'][:]))
dates=dates+dts.astype(int)
return(lon,lat,var,dates)
folder='D:\\shuju\\'
stem='China_1km_prep_*'
files=glob.glob(folder+stem)
#number of days exceeding these thresholds per year (wet days at lowest)
Pt = np.zeros((len(files), 1, 1))
for f in range(len(files)):
file_name=files[f]
var_name='prep'
yr0 = int(file_name.split('prep_')[1][0:4])
[lon,lat,pr,dates]=bring(file_name,var_name,yr0)
print(pr.ndim)
print(pr.shape)
#calculate number of wet days, and amount of rainon wet days, and amount of rain in excess of threshold, on a sequence of absolute thresholds
intermed=np.sum(pr,axis=0)
intermed = np.expand_dims(intermed, axis=0)
#append these wet days measures to the previous years values
Pt[f, :, :] = intermed
del intermed
del pr
print('done year ' + str(int(file_name.split('prep_')[1][0:4])))
mask = gpd.read_file('D:\\shuju\\shp\\liujingdexian\\LYDX.gpkg',layer=0)
isos=pd.unique(mask.OBJECTID_1)
for i in range(len(isos)):
measure = np.zeros((1, 1))
# load region specific coordinates and weights
crds_file = str(18) + '_crds_wghts.pkl'
if len(glob.glob(crds_file)) != 0:
with open(crds_file, 'rb') as f:
[loni_c, lati_c, weights_c] = pickle.load(f)
Z = Pt[:, lati_c, loni_c]
# apply coordinates and weightings to obtain region specific measures
if len(weights_c) != 0:
measure[0, :] = np.dot(Z, np.array(weights_c)) / sum(weights_c)
else:
measure[0, :] = np.nan
#save measures
np.save('secondary_data/measures/precip/Pt_' + str(i) + '.npy',measure)
这里对代码进行了一些修改,主要是将 Pt 数组的大小调整为 (len(files), 1, 1),以便在后续的计算中使用。另外,也删除了一些不必要的变量和语句。
如果以上回答对您有所帮助,点击一下采纳该答案~谢谢
引用chatGPT作答,这个错误通常是由于在调用bring函数时指定的lon_min、lon_max、lat_min和lat_max超出了数据的范围。请确保您传递给bring函数的经纬度边界值在数据的有效范围内,并且与数据本身的经纬度值匹配。
如果您已经确认经纬度边界值正确,那么您可以尝试打印出经纬度值以及经纬度边界值,以便更好地理解数据的范围和问题的根源。
例如,您可以在bring函数中添加以下代码,以在调用where函数之前打印经纬度值和范围:
print(lon)
print(lat)
print(lon_min, lon_max, lat_min, lat_max)
此外,您还可以将数据的范围可视化,以更好地了解数据的分布和问题的根源。可以使用matplotlib或其他可视化库将数据可视化,或将数据导入到GIS软件中进行可视化。