@@ -12,16 +12,16 @@ def tqdm(x, **kwargs):
1212 return x
1313
1414
15- def _calc_quad (x ,y ):
15+ def _calc_quad (x , y ):
1616 """
17- This is a simpler solution to calculate a cartesian quadrant.
17+ This is a simpler solution to calculate a cartesian quadrant.
1818
19- To explain graphically, let the tuple below be (off_sign[i], neg_y[i]*2).
19+ To explain graphically, let the tuple below be (off_sign[i], neg_y[i]*2).
2020
21- If sign(x[i]) != sign(y[i]), we are on the negative diagonal.
22- If y is negative, we are on the bottom of the plot.
21+ If sign(x[i]) != sign(y[i]), we are on the negative diagonal.
22+ If y is negative, we are on the bottom of the plot.
2323
24- Therefore, the sum (off_sign + neg_y*2 + 1) gives you the cartesian quadrant.
24+ Therefore, the sum (off_sign + neg_y*2 + 1) gives you the cartesian quadrant.
2525
2626 II | I
2727 1,0 | 0,0
@@ -31,12 +31,17 @@ def _calc_quad(x,y):
3131
3232 """
3333 off_sign = np .sign (x ) != np .sign (y )
34- neg_y = (y < 0 )
35- return off_sign + neg_y * 2 + 1
34+ neg_y = y < 0
35+ return off_sign + neg_y * 2 + 1
36+
3637
3738class MoranLocalPartial (object ):
3839 def __init__ (
39- self , permutations = 999 , unit_scale = True , partial_labels = True , alternative = 'two-sided'
40+ self ,
41+ permutations = 999 ,
42+ unit_scale = True ,
43+ partial_labels = True ,
44+ alternative = "two-sided" ,
4045 ):
4146 """
4247 Compute the Multivariable Local Moran statistics under partial dependence :cite:`wolf2024confounded`
@@ -52,12 +57,12 @@ def __init__(
5257 the covariance statistics are not overwhelmed by any single
5358 covariate's large variance.
5459 partial_labels : bool, default=True
55- whether to calculate the classification based on the part-regressive
60+ whether to calculate the classification based on the part-regressive
5661 quadrant classification or the univariate quadrant classification,
5762 like a classical Moran's I. When mvquads is True, the variables are labelled as:
58- - label 1: observations with large y - rho * x that also have large Wy values.
63+ - label 1: observations with large y - rho * x that also have large Wy values.
5964 - label 2: observations with small y - rho * x values that also have large Wy values.
60- - label 3: observations with small y - rho * x values that also have small Wy values.
65+ - label 3: observations with small y - rho * x values that also have small Wy values.
6166 - label 4: observations with large y - rho * x values that have small Wy values.
6267 alternative : str (default: 'two-sided')
6368 the alternative hypothesis for the inference. One of
@@ -97,13 +102,13 @@ def __init__(
97102 describing the relationship between y and Wy.
98103 labels_ : the (N,) array of quadrant classifications for the
99104 part-regressive relationships. See the partial_labels argument
100- for more information.
105+ for more information.
101106 """
102107 self .permutations = permutations
103108 self .unit_scale = unit_scale
104109 self .partial_labels = partial_labels
105110 self .alternative = alternative
106-
111+
107112 def fit (self , X , y , W ):
108113 """
109114 Fit the partial local Moran statistic on input data
@@ -118,7 +123,7 @@ def fit(self, X, y, W):
118123 to compute the multivariable Moran's I
119124 W : (N,N) weights object
120125 spatial weights instance as W or Graph aligned with y. Immediately row-standardized.
121-
126+
122127 Returns
123128 -------
124129 self : object
@@ -154,10 +159,10 @@ def fit(self, X, y, W):
154159 self ._rlmos_ *= self .N - 1
155160 self ._p_sim_ = np .zeros ((self .N , self .P + 1 ))
156161 for i in range (self .P + 1 ):
157- self ._p_sim_ [:,i ] = calculate_significance (
158- self ._lmos_ [:,i ],
159- self ._rlmos_ [:,:, i ],
160- alternative = self .alternative
162+ self ._p_sim_ [:, i ] = calculate_significance (
163+ self ._lmos_ [:, i ],
164+ self ._rlmos_ [:, :, i ],
165+ alternative = self .alternative ,
161166 )
162167
163168 component_quads = []
@@ -173,11 +178,11 @@ def fit(self, X, y, W):
173178 )
174179
175180 uvquads = []
176- negative_lag = R [:,1 ] < 0
181+ negative_lag = R [:, 1 ] < 0
177182 for i , x_ in enumerate (self .D .T ):
178183 if i == 0 :
179184 continue
180- off_sign = np .sign (x_ ) != np .sign (R [:,1 ])
185+ off_sign = np .sign (x_ ) != np .sign (R [:, 1 ])
181186 quads = negative_lag .astype (int ).flatten () * 2 + off_sign .astype (int ) + 1
182187 uvquads .append (quads .flatten ())
183188
@@ -186,7 +191,7 @@ def fit(self, X, y, W):
186191 return self
187192
188193 def _make_data (self , z , X , W ):
189- if isinstance (W , Graph ): # NOQA because ternary is confusing
194+ if isinstance (W , Graph ): # NOQA because ternary is confusing
190195 Wz = W .lag (z )
191196 else :
192197 Wz = lag_spatial (W , z )
@@ -212,7 +217,7 @@ def _crand(self, y, X, W):
212217 [np .random .permutation (N - 1 )[0 :max_neighbs ] for i in prange ]
213218 )
214219 straight_ids = np .arange (N )
215- if isinstance (W , Graph ): # NOQA
220+ if isinstance (W , Graph ): # NOQA
216221 id_order = W .unique_ids
217222 else :
218223 id_order = W .id_order
@@ -230,7 +235,7 @@ def _crand(self, y, X, W):
230235 shuffled_Wyi = (shuffled_ys * these_weights ).sum (
231236 axis = 1
232237 ) # these are N-permutations by 1 now
233- # shuffled_X = X[randomized_permutations, :]
238+ # shuffled_X = X[randomized_permutations, :]
234239 # #these are still N-permutations, N-neighbs, N-covariates
235240 if X is None :
236241 local_data = np .array ((1 , y [i ].item ())).reshape (1 , - 1 )
@@ -320,7 +325,7 @@ def __init__(
320325 permutations = 999 ,
321326 unit_scale = True ,
322327 transformer = None ,
323- alternative = ' two-sided'
328+ alternative = " two-sided" ,
324329 ):
325330 """
326331 Initialize a local Moran statistic on the regression residuals
@@ -366,7 +371,7 @@ def __init__(
366371 describing the relationship between y and Wy.
367372 labels_ : the (N,) array of quadrant classifications for the
368373 part-regressive relationships. See the partial_labels argument
369- for more information.
374+ for more information.
370375 """
371376 self .permutations = permutations
372377 self .unit_scale = unit_scale
@@ -385,7 +390,7 @@ def fit(self, X, y, W):
385390 to account for their covariance with Y.
386391 W : (N,N) weights object
387392 spatial weights instance as W or Graph aligned with y. Immediately row-standardized.
388-
393+
389394 Returns
390395 -------
391396 A fitted MoranLocalConditional() estimator
@@ -403,15 +408,19 @@ def fit(self, X, y, W):
403408 Wyf = W .lag (y_filtered_ )
404409 else :
405410 W .transform = "r"
406- Wyf = lag_spatial (W , y_filtered_ ) # TODO: graph
411+ Wyf = lag_spatial (W , y_filtered_ ) # TODO: graph
407412 self .connectivity = W
408413 self .partials_ = np .column_stack ((y_filtered_ , Wyf ))
409414 y_out = self .y_filtered_
410415 self .association_ = ((y_out * Wyf ) / (y_out .T @ y_out ) * (W .n - 1 )).flatten ()
411416 if self .permutations > 0 :
412417 self ._crand ()
413- self .significance_ = calculate_significance (self .association_ , self .reference_distribution_ , alternative = self .alternative )
414- quads = np .array ([[3 ,2 ,4 ,1 ]]).reshape (2 ,2 )
418+ self .significance_ = calculate_significance (
419+ self .association_ ,
420+ self .reference_distribution_ ,
421+ alternative = self .alternative ,
422+ )
423+ quads = np .array ([[3 , 2 , 4 , 1 ]]).reshape (2 , 2 )
415424 left_component_cluster = (y_filtered_ > 0 ).astype (int )
416425 right_component_cluster = (Wyf > 0 ).astype (int )
417426 quads = quads [left_component_cluster , right_component_cluster ]
0 commit comments