Skip to content

Commit ab55926

Browse files
0.24.25
1 parent 72844ad commit ab55926

2 files changed

Lines changed: 58 additions & 1 deletion

File tree

pyproject.toml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,7 @@ build-backend = "setuptools.build_meta"
77

88
[project]
99
name = "spotpython"
10-
version = "0.24.24"
10+
version = "0.24.25"
1111
authors = [
1212
{ name="T. Bartz-Beielstein", email="tbb@bartzundbartz.de" }
1313
]

src/spotpython/utils/stats.py

Lines changed: 57 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -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

Comments
 (0)