Last active
August 29, 2024 17:28
-
-
Save wladston/c931b1495184fbb99bec to your computer and use it in GitHub Desktop.
Distance correlation with p-value
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
from scipy.spatial.distance import pdist, squareform | |
import numpy as np | |
import copy | |
def distcorr(Xval, Yval, pval=True, nruns=500): | |
""" Compute the distance correlation function, returning the p-value. | |
Based on Satra/distcorr.py (gist aa3d19a12b74e9ab7941) | |
>>> a = [1,2,3,4,5] | |
>>> b = np.array([1,2,9,4,4]) | |
>>> distcorr(a, b) | |
(0.76267624241686671, 0.266) | |
""" | |
X = np.atleast_1d(Xval) | |
Y = np.atleast_1d(Yval) | |
if np.prod(X.shape) == len(X): | |
X = X[:, None] | |
if np.prod(Y.shape) == len(Y): | |
Y = Y[:, None] | |
X = np.atleast_2d(X) | |
Y = np.atleast_2d(Y) | |
n = X.shape[0] | |
if Y.shape[0] != X.shape[0]: | |
raise ValueError('Number of samples must match') | |
a = squareform(pdist(X)) | |
b = squareform(pdist(Y)) | |
A = a - a.mean(axis=0)[None, :] - a.mean(axis=1)[:, None] + a.mean() | |
B = b - b.mean(axis=0)[None, :] - b.mean(axis=1)[:, None] + b.mean() | |
dcov2_xy = (A * B).sum() / float(n * n) | |
dcov2_xx = (A * A).sum() / float(n * n) | |
dcov2_yy = (B * B).sum() / float(n * n) | |
dcor = np.sqrt(dcov2_xy) / np.sqrt(np.sqrt(dcov2_xx) * np.sqrt(dcov2_yy)) | |
if pval: | |
greater = 0 | |
for i in range(nruns): | |
Y_r = copy.copy(Yval) | |
np.random.shuffle(Y_r) | |
if distcorr(Xval, Y_r, pval=False) > dcor: | |
greater += 1 | |
return (dcor, greater / float(nruns)) | |
else: | |
return dcor |
I tried running distcorr([1,2,3],[2,4,6], nruns=100000)
both shuffling Xval and not shuffling it. Both cases returns a distance correlation of 1 with p-value of 0.33. This means that in both cases, 33% of the random shuffles also produce a distance correlation of 1. If we change if distcorr(Xval, Y_r, pval=False) >= dcor
to > dcor
, then no random shuffling makes that line be true, and the p-value is zero. I'm unsure whether we should use >
instead of >=
, but I've made the change anyways, because in the example you described it makes sense that the the p-value is zero.
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Hi,
I think Xval should be shuffled with Yval. or your distcorr([1,2,3],[2,4,6]) will not give the correct p-value, 1 in this case.