stefanuddenberg
12/7/2019 - 2:26 AM

Pingouin & Pandas -- Get partial correlations of DataFrame

import pandas as pd
import pingouin as pg

# doesn't look like you need to read the df in with pg
df.pcorr() # for table of all pcorrs

# to get p-vals
# Partial correlation of x and y controlling for cv1, cv2 and cv3
df.partial_corr(x='x', y='y', covar=['cv1', 'cv2', 'cv3'], method='spearman')
#           n      r         CI95%     r2  adj_r2     p-val  power
# spearman  30  0.568  [0.26, 0.77]  0.323   0.273  0.001049  0.925
# Other code I got online, gives different results
from scipy import stats, linalg

def partial_corr(C):
    """
    Returns the sample linear partial correlation coefficients between pairs of variables in C, controlling 
    for the remaining variables in C.
    Parameters
    ----------
    C : array-like, shape (n, p)
        Array with the different variables. Each column of C is taken as a variable
    Returns
    -------
    P : array-like, shape (p, p)
        P[i, j] contains the partial correlation of C[:, i] and C[:, j] controlling
        for the remaining variables in C.
    """

    C = np.asarray(C)
    p = C.shape[1]
    P_corr = np.zeros((p, p), dtype=np.float)
    for i in range(p):
        P_corr[i, i] = 1
        for j in range(i + 1, p):
            idx = np.ones(p, dtype=np.bool)
            idx[i] = False
            idx[j] = False
            beta_i = linalg.lstsq(C[:, idx], C[:, j])[0]
            beta_j = linalg.lstsq(C[:, idx], C[:, i])[0]

            res_j = C[:, j] - C[:, idx].dot(beta_i)
            res_i = C[:, i] - C[:, idx].dot(beta_j)

            corr = stats.pearsonr(res_i, res_j)[0]
            P_corr[i, j] = corr
            P_corr[j, i] = corr

    return P_corr