The median filter in scipy.signal is not optimal. Following this discussion, there are much faster implementations, even in pure python. However, the fastest method used here, running_median_insort, is not a drop-in replacement for scipy.signal.medfilt as it does not calculate the central median but the right sided median. However, by zero-padding as in the code below the behavior of the scipy implementation is exactly reproduced.

def running_median_insort(seq, window_size):
    Based on
    result = zeros_like(seq)
    padded_seq = zeros(len(seq) + window_size)
    padded_seq[window_size//2+1:window_size//2+1+len(seq)] = seq

    d = deque()

    s = padded_seq[:window_size]
    s = s.tolist()

    seq = iter(padded_seq[window_size:])
    m = window_size // 2
    c = 0
    for item in seq:
        old = d.popleft()
        del s[bisect_left(s, old)]
        insort(s, item)
        result[c] = s[m]
    return result

Applying the filter with width 1023 on an example of some 2^15+1 data samples takes 50.3 ms on my laptop, compared to 2.65s for the medfilter in scipy v0.18 while there is no difference between the results.

Example of median filter