@@ -268,7 +268,7 @@ def nancorr(const float64_t[:, :] mat, bint cov=False, minp=None):
268
268
ndarray[float64_t, ndim= 2 ] result
269
269
ndarray[uint8_t, ndim= 2 ] mask
270
270
int64_t nobs = 0
271
- float64_t vx, vy, sumx, sumy, sumxx, sumyy, meanx, meany, divisor
271
+ float64_t vx, vy, meanx, meany, divisor, prev_meany, prev_meanx, ssqdmx, ssqdmy, covxy
272
272
273
273
N, K = (< object > mat).shape
274
274
@@ -283,37 +283,28 @@ def nancorr(const float64_t[:, :] mat, bint cov=False, minp=None):
283
283
with nogil:
284
284
for xi in range (K):
285
285
for yi in range (xi + 1 ):
286
- nobs = sumxx = sumyy = sumx = sumy = 0
286
+ nobs = ssqdmx = ssqdmy = covxy = meanx = meany = 0
287
287
for i in range (N):
288
288
if mask[i, xi] and mask[i, yi]:
289
289
vx = mat[i, xi]
290
290
vy = mat[i, yi]
291
291
nobs += 1
292
- sumx += vx
293
- sumy += vy
292
+ prev_meanx = meanx
293
+ prev_meany = meany
294
+ meanx = meanx + 1 / nobs * (vx - meanx)
295
+ meany = meany + 1 / nobs * (vy - meany)
296
+ ssqdmx = ssqdmx + (vx - meanx) * (vx - prev_meanx)
297
+ ssqdmy = ssqdmy + (vy - meany) * (vy - prev_meany)
298
+ covxy = covxy + (vx - meanx) * (vy - prev_meany)
294
299
295
300
if nobs < minpv:
296
301
result[xi, yi] = result[yi, xi] = NaN
297
302
else :
298
- meanx = sumx / nobs
299
- meany = sumy / nobs
300
-
301
- # now the cov numerator
302
- sumx = 0
303
- for i in range (N):
304
- if mask[i, xi] and mask[i, yi]:
305
- vx = mat[i, xi] - meanx
306
- vy = mat[i, yi] - meany
307
-
308
- sumx += vx * vy
309
- sumxx += vx * vx
310
- sumyy += vy * vy
311
-
312
- divisor = (nobs - 1.0 ) if cov else sqrt(sumxx * sumyy)
303
+ divisor = (nobs - 1.0 ) if cov else sqrt(ssqdmx * ssqdmy)
313
304
314
305
# numerical issues for constant columns
315
- if divisor > 1e-15 :
316
- result[xi, yi] = result[yi, xi] = sumx / divisor
306
+ if divisor ! = 0 :
307
+ result[xi, yi] = result[yi, xi] = covxy / divisor
317
308
else :
318
309
result[xi, yi] = result[yi, xi] = NaN
319
310
@@ -323,6 +314,7 @@ def nancorr(const float64_t[:, :] mat, bint cov=False, minp=None):
323
314
# Pairwise Spearman correlation
324
315
325
316
317
+
326
318
@ cython.boundscheck (False )
327
319
@ cython.wraparound (False )
328
320
def nancorr_spearman (const float64_t[:, :] mat , Py_ssize_t minp = 1 ) -> ndarray:
0 commit comments