@@ -141,3 +141,60 @@ def pairwise_partial_correlation(x, y, z, method="pearson") -> dict:
141141 "gp" : pcor_result ["gp" ],
142142 "method" : method ,
143143 }
144+
145+
146+ def semi_partial_correlation (x , method = "pearson" ):
147+ if isinstance (x , pd .DataFrame ):
148+ x = x .to_numpy ()
149+ if not isinstance (x , np .ndarray ):
150+ raise ValueError ("Supply a matrix-like 'x'" )
151+ if not np .issubdtype (x .dtype , np .number ):
152+ raise ValueError ("'x' must be numeric" )
153+
154+ n = x .shape [0 ]
155+ gp = x .shape [1 ] - 2
156+ cvx = np .cov (x , rowvar = False , bias = True )
157+
158+ try :
159+ if np .linalg .det (cvx ) < np .finfo (float ).eps :
160+ icvx = pinv (cvx )
161+ else :
162+ icvx = inv (cvx )
163+ except LinAlgError :
164+ icvx = pinv (cvx )
165+
166+ sp_cor = - cov_to_cor (icvx ) / np .sqrt (np .diag (cvx )) / np .sqrt (np .abs (np .diag (icvx ) - np .square (icvx .T ) / np .diag (icvx )))
167+ np .fill_diagonal (sp_cor , 1 )
168+
169+ if method == "kendall" :
170+ denominator = np .sqrt (2 * (2 * (n - gp ) + 5 ) / (9 * (n - gp ) * (n - 1 - gp )))
171+ statistic = sp_cor / denominator
172+ p_value = 2 * norm .cdf (- np .abs (statistic ))
173+ else :
174+ factor = np .sqrt ((n - 2 - gp ) / (1 - sp_cor ** 2 ))
175+ statistic = sp_cor * factor
176+ p_value = 2 * t .cdf (- np .abs (statistic ), df = n - 2 - gp )
177+
178+ np .fill_diagonal (statistic , 0 )
179+ np .fill_diagonal (p_value , 0 )
180+
181+ return {"estimate" : sp_cor , "p_value" : p_value , "statistic" : statistic , "n" : n , "gp" : gp , "method" : method }
182+
183+
184+ def pairwise_semi_partial_correlation (x , y , z , method = "pearson" ):
185+ x = np .asarray (x )
186+ y = np .asarray (y )
187+ z = pd .DataFrame (z )
188+
189+ xyz = pd .concat ([pd .Series (x ), pd .Series (y ), z ], axis = 1 )
190+
191+ spcor_result = semi_partial_correlation (xyz , method = method )
192+
193+ return {
194+ "estimate" : spcor_result ["estimate" ][0 , 1 ],
195+ "p_value" : spcor_result ["p_value" ][0 , 1 ],
196+ "statistic" : spcor_result ["statistic" ][0 , 1 ],
197+ "n" : spcor_result ["n" ],
198+ "gp" : spcor_result ["gp" ],
199+ "method" : method ,
200+ }
0 commit comments