-
Notifications
You must be signed in to change notification settings - Fork 0
/
statistics_Danilo.py
163 lines (151 loc) · 4.57 KB
/
statistics_Danilo.py
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
# Souza & Ramos da Silva,
# Ocean-Land Atmosphere Model (OLAM) performance for major extreme
# meteorological events near the coastal region of southern Brazil,
# Climate Research, in revision 2020
"""
Created on Thu Jan 21 18:06:04 2021
Script created to perform the statistics analysis.
Altough that for some analysis perfomed here, there were already some
specific modules, we prefered to do them from scratch, whenever possible.
@author: Danilo
"""
#
import numpy as np
from scipy import stats
# ----------
def di_acc(obs, olam):
'''
Calculate difference (di) between observation and simulation for total acc. prec.
'''
diff = olam - obs
return diff
# ----------
def BIAS(obs, olam):
'''
Calculate model Bias, or sistematic error based on the 'di'
'''
diff = di_acc(obs, olam)
tmp = diff.sum('lon').sum('lat').values
return tmp/(diff.shape[0]*diff.shape[1])
# ----------
def MAE(obs, olam):
'''
Calculate model Mean Absolute Error based on the 'di'
'''
abs_diff = abs(di_acc(obs, olam))
tmp = abs_diff.sum('lon').sum('lat').values
return tmp/(abs_diff.shape[0]*abs_diff.shape[1])
# ----------
def MSE(obs, olam):
'''
Calculate model Mean Square Error based on the 'di'
'''
diff_sqr = di_acc(obs, olam)**2
tmp = diff_sqr.sum('lon').sum('lat').values
N = diff_sqr.size
return tmp/N
# ----------
def MSE_diss(obs, olam):
'''
Calculate the model Dissipative Mean Square Error based on the 'di'
'''
tmp1 = (np.nanstd(obs.values) - np.nanstd(olam.values))**2
tmp2 = (np.nanmean(obs.values) - np.nanmean(olam.values))**2
return tmp1+tmp2
# ----------
def covariance(obs, olam):
'''
Calculate Covariance between model and reanalysis
'''
ave_olam = np.mean(olam)
ave_obs = np.mean(obs)
tmp = (olam - ave_olam) * (obs - ave_obs)
tmp = tmp.sum('lon').sum('lat').values
N = olam.size
return tmp/(N-1)
# ----------
def Scorr(obs, olam):
'''
Calculate Spatial Correlation between model and reanalysis using 3 methods
'''
cov = covariance(obs, olam)
pcorr = cov/(np.nanstd(obs.values) * np.nanstd(olam.values))
scorr, _ = stats.spearmanr(obs.values, olam.values,axis=None)
kcorr, _ = stats.kendalltau(obs.values, olam.values)
return pcorr, scorr, kcorr
# ----------
def MSE_disp(obs, olam):
'''
Calculate the model Dispersive Mean Square Error based on the 'di'
'''
p = Scorr(obs, olam)[0]
# p = Scorr(obs, olam)
tmp1 = 2*(1-p)
tmp2 = np.nanstd(obs.values) * np.nanstd(olam.values)
return tmp1*tmp2
# ----------
def RMSE(obs, olam):
'''
Calculate model Root Mean Square Error based on the 'di'
'''
diff_sqr = di_acc(obs, olam)**2
tmp = diff_sqr.sum('lon').sum('lat').values
N = diff_sqr.size
tmp = tmp/N
return np.sqrt(tmp)
# ----------
def RMSE_bias(obs, olam):
'''
Calculate model RMSE after constant bias removal
'''
obs_mean = np.mean(obs)
olam_mean = np.mean(olam)
N = olam.size
tmp = ((obs-obs_mean) - (olam-olam_mean))**2
tmp = (tmp.sum('lon').sum('lat').values)/N
return np.sqrt(tmp)
# ----------
def S_sqr(obs, olam):
'''
Calculate the Differences Variance (Sd^2)
'''
diff = di_acc(obs, olam)
N = diff.size
diff_m = np.nanmean(diff.values)
tmp = (diff-diff_m)**2
tmp = tmp.sum('lon').sum('lat').values
return tmp/(N-1)
# ----------
def ConcordanceIndex(obs, olam):
'''
Calculate Concordnce Index (Willmot, 1982)
'''
diff_sqr = di_acc(obs, olam)**2
top = diff_sqr.sum('lon').sum('lat').values
obs_m = np.mean(obs).values
tmp1 = np.abs(olam - obs_m)
tmp2 = np.abs(obs - obs_m)
tmp = (tmp1+tmp2)**2
bottom = tmp.sum('lon').sum('lat').values
return 1-(top/bottom)
# ----------
def D_pielke(obs, olam):
'''
Calculate Pielke Model's Dexterity (Pielke, 2002)
'''
obs_v = obs.values
tmp1 = np.abs(1-(np.nanstd(olam.values)/np.nanstd(obs_v)))
tmp2 = RMSE(obs, olam)/np.nanstd(obs_v)
tmp3 = RMSE_bias(obs, olam)/np.nanstd(obs_v)
return tmp1+tmp2+tmp3
# ----------
def linear_regression(x, y):
# from https://towardsdatascience.com/simple-linear-regression-in-python-numpy-only-130a988c0212
x_mean = x.mean()
y_mean = y.mean()
B1_num = ((x - x_mean) * (y - y_mean)).sum()
B1_den = ((x - x_mean)**2).sum()
B1 = B1_num / B1_den
B0 = y_mean - (B1*x_mean)
reg_line = 'y = {} + {}β'.format(B0, round(B1, 3))
return (B0, B1, reg_line)