PDO指数计算及其Python代码实现

本文详细介绍了利用Python进行太平洋DecadalOscillation(PDO)指数的计算,涉及数据预处理、EOF分析方法及结果可视化。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

目录

一:PDO指数

二:实验数据准备

三:python代码

四:实验结果


一:PDO指数

  PDO(Pacific Decadal Oscillation)通常被描述为太平洋气候变率的一种长期的类似厄尔尼诺现象的模式。PDOENSO有三个主要区别:第一,20世纪的PDO"事件"持续2030年,而典型的ENSO事件持续618个月;第二,PDO的气候特征在外侧热带地区最明显,尤其是北太平洋/北美地区,而次要特征则在热带地区,ENSO的情况正好相反;第三,导致PDO变异的机制尚不清楚,而导致ENSO变异的原因则相对清楚。

  本文PDO指数的计算方法为:北太平洋(20°N-70°N,110°E-100°W)SST数据每个网格点上的月平均SST距平值减去相应月份全球平均的SST距平值,以去除SST资料中的全球增暖趋势,对去趋势后的数据进行EOF分析,得到的第一特征向量场的时间序列(PC1)即为PDO指数值。

  其中EOF分析即经验正交函数分析。EOF分析是通过将时空数据集转化成物理量的空间模态和与之相联系时间上的投影(时间序列),来简化该时空数据集。这些空间模态就是EOFs,可以被看作是方差对应的基函数(空间中的一组基向量)。相关的时间投影是主要成分(PCs),是EOFs的时间系数。

   SSTA去除趋势的计算公式如下:

                                        SSTA_{x,y,t}^{*}=SSTA_{x,y,t} -[SSTA] _{t}

(参考文献:Yuan Zhang, John M. Wallace, David S. Battisti. ENSO-like Interdecadal Variability: 1900?93. Journal of Climate, 1997, 10:1004-1020)

二:实验数据准备

本文采用ERSST V5数据集的SST月平均数据

下载网址:https://downloads.psl.noaa.gov/Datasets/noaa.ersst.v5/

时间覆盖范围:1854/01-2023/09   

空间覆盖范围:88.0N-88.0S,0.0E-358.0E(2.0 度纬度 x 2.0 度经度全球网格)

三:python代码

import numpy as np
import xarray as xr
import scipy   
from eofs.standard import Eof
import matplotlib.pyplot as plt
import cartopy.crs as ccrs #crs即坐标参考系统(Coordinate Reference Systems)
import cartopy.feature as cfeature  #添加地图特征,如国界、海岸线等
from cartopy.mpl.ticker import LongitudeFormatter, LatitudeFormatter 

#忽略警告信息
import warnings
warnings.filterwarnings('ignore')


#文件读取
path='G:\\python\\sst.mnmean.nc'
dataset = xr.open_dataset(path)

sst = dataset['sst']   
sst_loc = sst.loc['1900-01-01':'2022-12-01'].loc[:,70:20,110:260]
ssta_loc=sst_loc.groupby('time.month')-sst_loc.groupby('time.month').mean('time', skipna=True)

sst_all = sst.loc['1900-01-01':'2022-12-01']
ssta_all = sst_all.groupby('time.month')-sst_all.groupby('time.month').mean('time', skipna=True)
ssta_all=np.array(ssta_all)

ssta_detrend = np.empty((1476,26,76))
for time in np.arange(1476):
    for lat in np.arange(26):
        for lon in np.arange(76):
            ssta_detrend[time,lat,lon]=np.nanmean(ssta_all[time,:,:])

ssta_loc=np.array(ssta_loc)
ssta = ssta_loc-ssta_detrend

#计算纬度权重
Lat = sst_loc.lat[:]
lat=np.array(Lat)
coslat=np.cos(np.deg2rad(lat))  
wgts = np.sqrt(coslat)[:, np.newaxis]  

solver=Eof(ssta,weights=wgts)
eof=solver.eofsAsCorrelation(neofs=3)*(-1)   #空间模态
pc=solver.pcs(npcs=3,pcscaling=1)*(-1)       #时间模态
var=solver.varianceFraction(neigs=3)    #方差贡献率

#绘图自定义函数
def mapart(ax):
    
    ax.add_feature(cfeature.COASTLINE,color="k",lw=0.5)  #绘制海岸线  k:黑色  lw为线宽
    ax.add_feature(cfeature.LAND,facecolor="white") #添加陆地  facecolor同color

    leftlon,rightlon,lowerlat,upperlat=(110,260,20,70)   #设置经纬范围
    ax.set_extent([leftlon,rightlon,lowerlat,upperlat],crs=ccrs.PlateCarree()) 
    ax.set_xticks(np.arange(leftlon,rightlon,20),crs=ccrs.PlateCarree())    
    ax.set_yticks(np.arange(lowerlat,upperlat+5,10),crs=ccrs.PlateCarree())
    
    lon_formatter = LongitudeFormatter()
    lat_formatter = LatitudeFormatter()
    ax.xaxis.set_major_formatter(lon_formatter)
    ax.yaxis.set_major_formatter(lat_formatter)


def eof_contourf(eofs,pcs,pers):
#该函数绘制前三个模态的EOF和PC   绘图三部曲,画布,投影,子图  
    plt.close 
    fig=plt.figure(figsize=(18,10))   #添加画布 figsize=(宽,高)  
    proj=ccrs.PlateCarree(central_longitude=180)  #设置投影类型,并指定中央经线
    lon=np.arange(110,262,2)
    lat=np.arange(70,18,-2)
  
    ax1=fig.add_subplot(321,projection=proj) #添加三行两列子图中第一个子图,即EOF1
    mapart(ax1)
    p=ax1.contourf(lon,lat,eofs[0,:,:],levels=np.arange(-0.9,1.0,0.1), zorder=0, extend = 'both',transform=ccrs.PlateCarree(), cmap=plt.cm.RdBu_r)
    ax1.set_title('mode1 (%s'%(round(pers[0],2))+"%)",loc ='left')

 
    ax2=fig.add_subplot(322)  #添加三行两列子图中第二个子图,即PC1
    ax2.plot(np.arange(1900,2023,1/12),pcs[:,0],color="k",linewidth=2,linestyle="--")  
    ax2.set_title('pc1 (%s'%(round(pers[0],2))+"%)",loc ='left')
    
    ax3 = fig.add_subplot(323, projection=proj)  #添加三行两列子图中第三个子图,即EOF2
    mapart(ax3)
    pp = ax3.contourf(lon,lat,eofs[1,:,:],levels=np.arange(-0.9,1.0,0.1), zorder=0, extend = 'both',transform=ccrs.PlateCarree(), cmap=plt.cm.RdBu_r)
    ax3.set_title('mode2 (%s'%(round(pers[1],2))+"%)",loc ='left')
    
    ax4 = fig.add_subplot(324)  #添加三行两列子图中第四个子图,即PC2
    ax4.plot(np.arange(1900,2023,1/12),pcs[:,1] ,color='k',linewidth=1.2,linestyle='--')
    ax4.set_title('pc2 (%s'%(round(pers[1],2))+"%)",loc ='left')
    
    ax5 = fig.add_subplot(325, projection=proj)   #添加三行两列子图中第五个子图,即EOF3
    mapart(ax5)
    ppp = ax5.contourf(lon,lat,eofs[2,:,:],levels=np.arange(-0.9,1.0,0.1), zorder=0, extend = 'both',transform=ccrs.PlateCarree(), cmap=plt.cm.RdBu_r)
    ax5.set_title('mode3 (%s'%(round(pers[2],2))+"%)",loc ='left')
    
    ax6 = fig.add_subplot(326)  #添加三行两列子图中第六个子图,即PC3
    ax6.plot(np.arange(1900,2023,1/12),pcs[:,2],color='k',linewidth=1.2,linestyle='--')
    ax6.set_title('pc3 (%s'%(round(pers[2],2))+"%)",loc ='left')
    
    #添加0线
    ax2.axhline(y=0,  linewidth=1, color = 'k',linestyle='-')
    ax4.axhline(y=0,  linewidth=1, color = 'k',linestyle='-')
    ax6.axhline(y=0,  linewidth=1, color = 'k',linestyle='-')
    
    #在图下边留白边放colorbar        
    fig.subplots_adjust(bottom=0.1,wspace=0.12,hspace=0.3)  #调整子图位置 subplots_adjust(left=,bottom=,top=,right=,hspace=,wspace=)
    cbar_ax = fig.add_axes([0.25,0.04,0.6,0.015]) #[x0, y0, width, height] x0,y0为左下点在图中坐标 width,height为宽度和高度
    
    c=plt.colorbar(pp, cax=cbar_ax,orientation='horizontal')
    c.ax.tick_params(labelsize=6)  #参数labelsize用于设置刻度线标签的字体大小

    plt.savefig('eof_detrend.tif',dpi=600,bbox_inches = 'tight',transparent=True, pad_inches = 0)  #将绘图结果存储成tif图片
    plt.show()

eof_contourf(eof,pc,var*100)

四:实验结果

  上图中PC1即为所求的PDO指数,将所求的PDO指数与美国国家海洋和大气管理局(NOAA)发布的PDO指数进行对比,比较结果如下,相关系数为0.981544。

noaa_PDO指数数据下载网址:https://www.ncei.noaa.gov/pub/data/cmb/ersst/v5/index/ersst.v5.pdo.dat

### Python 实现催收评分卡代码示例 #### 数据准备与加载 首先,确保数据已经经过适当清理和预处理。这里假设已经有了一个干净的数据集 `collections_data.csv`。 ```python import pandas as pd from sklearn.model_selection import train_test_split from sklearn.preprocessing import StandardScaler, OneHotEncoder from category_encoders.ordinal import OrdinalEncoder from sklearn.compose import ColumnTransformer from sklearn.pipeline import Pipeline from sklearn.linear_model import LogisticRegression from sklearn.metrics import roc_auc_score, classification_report import numpy as np # 加载数据 data = pd.read_csv('./data/collections_data.csv') # 特征工程:选择特征列并定义转换器 numeric_features = ['age', 'income'] categorical_features = ['gender', 'education_level'] preprocessor = ColumnTransformer( transformers=[ ('num', StandardScaler(), numeric_features), ('cat', OneHotEncoder(handle_unknown='ignore'), categorical_features)]) X = data.drop(['default'], axis=1) y = data['default'] # 划分训练集和测试集 X_train, X_test, y_train, y_test = train_test_split(X, y, test_size=0.25, random_state=42) # 构建管道 pipeline = Pipeline(steps=[('preprocessor', preprocessor), ('classifier', LogisticRegression())]) # 训练模型 pipeline.fit(X_train, y_train) # 预测概率得分 probs = pipeline.predict_proba(X_test)[:, 1] # 输出AUC评估指标 print(f"AUC Score: {roc_auc_score(y_test, probs)}") # 打印分类报告 predictions = (probs >= 0.5).astype(int) print(classification_report(y_test, predictions)) ``` 这段代码展示了如何构建一个简单的二元逻辑回归模型用于预测违约可能性,并计算了 AUC 值来衡量性能[^3]。 #### 创建评分函数 基于上述模型的结果,下面是一个简化版的评分机制: ```python def get_score(probability): """ 将违约概率转化为分数. 参数: probability (float): 违约的概率 返回: int: 对应于输入概率的风险评价值 """ base_points = 600 # 设定基础分为600分 odds_ratio = probability / (1 - probability) factor = 20 / np.log(2) # 定义PDO为20点每倍数变化 offset = 600 - factor * np.log(odds_ratio) score = round(base_points + offset) return max(min(score, 900), 300) # 控制范围在300至900之间 # 应用评分函数到测试集中每个样本 scores = [get_score(p) for p in probs] ``` 此部分实现了将连续型的概率输出映射成离散化的信用评分体系,其中包含了基本参数设定如基础分、比例因子等[^2]。
评论 6
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值