@@ -163,11 +163,14 @@ def moving_median_over_zeroth_axis(x: np.ndarray, w: int) -> np.ndarray:
163163 """
164164 Calculate the median of a moving window over the zeroth axis of an N-d array.
165165
166- Algorithm works by expanding the array into an additional dimension
167- where the new axis has the same length as the window size. Each entry in that
168- axis is a copy of the original array shifted by 1 with respect to the previous
169- entry, such that the rolling median is simply the median over the new axis.
170- modified from https://stackoverflow.com/a/71154394, see link for more details.
166+ Slide a window of size w over the array along axis 0, and for each position,
167+ calculate the median of the values inside that window (across axis 0 only).
168+ The result at each step is stored in the center position of the window,
169+ producing an output array with the same shape as the input.
170+
171+ Because the window cannot fully overlap the data at the beginning and end,
172+ those edge positions are filled with the nearest computed median value to
173+ avoid missing data.
171174
172175 Parameters
173176 ----------
@@ -183,17 +186,15 @@ def moving_median_over_zeroth_axis(x: np.ndarray, w: int) -> np.ndarray:
183186 """
184187 if w <= 1 :
185188 raise ValueError ("Rolling median window size must be greater than 1." )
186- shifted = np .zeros ((x .shape [0 ] + w - 1 , w , * x .shape [1 :])) * np .nan
187- for idx in range (w - 1 ):
188- shifted [idx : - w + idx + 1 , idx ] = x
189- shifted [idx + 1 :, idx + 1 ] = x
190- medians : np .ndarray = np .median (shifted , axis = 1 )
191- for idx in range (w - 1 ):
192- medians [idx ] = np .median (shifted [idx , : idx + 1 ])
193- medians [- idx - 1 ] = np .median (shifted [- idx - 1 , - idx - 1 :])
194- medians = medians [(w - 1 ) // 2 : - (w - 1 ) // 2 ]
195-
189+ out = np .full (x .shape , np .nan )
190+ hw , odd_window = divmod (w , 2 )
191+ for start_index in range (x .shape [0 ] - w + 1 ):
192+ end_index = start_index + w
193+ np .median (x [start_index :end_index ], axis = 0 , out = out [start_index + hw ])
196194 # Fill in the edges with the nearest valid value
197- medians [: w // 2 ] = medians [w // 2 ]
198- medians [- w // 2 :] = medians [- w // 2 ]
199- return medians
195+ out [:hw ] = out [hw ]
196+ if odd_window :
197+ out [- hw :] = out [- hw - 1 ]
198+ else :
199+ out [- hw + 1 :] = out [- hw ]
200+ return out
0 commit comments