在不等维度上移动窗口平均值

时间:2017-08-25 09:50:19

标签: python numpy

TL; DR:无论如何,我可以摆脱我的第二个for - 循环吗?

我在2D网格上有一系列时间点。为了消除它们位置的快速波动,我在一个帧窗口上平均坐标。现在在我的情况下,这些点可能比平时覆盖更大的距离。如果特定点的帧数超过cut_off值,我不想包含特定点的帧。

在第一个for循环中,我遍历所有帧并定义移动窗口。然后,我计算当前帧与移动窗口中每个帧之间的距离。在我仅抓取所有框架中的那些位置后,xy组件的行进距离都不超过cut_off。现在我想计算移动窗口所有这些选定帧中每个点的平均位置(注意:所选帧的数量 小于{{1} })。这导致我进入第二个n_window循环。在这里,我迭代所有点并实际抓住帧中的位置,其中当前点的行程比for更远。从这些选定的帧中,我计算坐标的平均值,并将其用作当前帧的新值。

这最后一个cut_off循环减缓了整个处理过程。我无法想出一个更好的方法来完成这个计算。有什么建议吗?

MWE

提出意见澄清。

for

1 个答案:

答案 0 :(得分:0)

如果您可以分别计算x和y中的截止距离,则可以使用scipy.ndimage.generic_filter

enter image description here

import numpy as np
from scipy.ndimage import generic_filter

def _mean(x, cutoff):
    is_too_different = np.abs(x - x[len(x) / 2]) > cutoff
    return np.mean(x[~is_too_different])

def _smooth(x, window_length=5, cutoff=1.):
    return generic_filter(x, _mean, size=window_length, mode='nearest', extra_keywords=dict(cutoff=cutoff))

def smooth(arr, window_length=5, cutoff=1., axis=-1):
    return np.apply_along_axis(_smooth, axis, arr, window_length=window_length, cutoff=cutoff)

# --------------------------------------------------------------------------------

def _simulate_movement_2d(T, fraction_is_jump=0.01):

    # generate random velocities with a few "jumps"
    velocity = np.random.randn(T, 2)
    is_jump = np.random.rand(T) < fraction_is_jump
    jump = 10 * np.random.randn(T, 2)
    jump[~is_jump] = 0.

    # pre-allocate position and momentum arrays
    position = np.zeros((T,2))
    momentum = np.zeros((T,2))

    # initialise the first position
    position[0] = np.random.randn(2)

    # update position using velocity vector:
    # smooth movement by not applying the velocity directly
    # but rather by keeping track of the momentum
    for ii in range(2,T):
        momentum[ii] = 0.9 * momentum[ii-1] + 0.1 * velocity[ii-1]
        position[ii] = position[ii-1] + momentum[ii] + jump[ii]

    # add some measurement noise
    noise = np.random.randn(T,2)
    position += noise
    return position

def demo(nframes=1000, npoints=3):
    # create data
    positions = np.array([_simulate_movement_2d(nframes) for ii in range(npoints)])

    # format to (nframes, npoints, 2)
    position = positions.transpose([1, 0, 2])

    # smooth
    smoothed = smooth(positions, window_length=11, cutoff=5., axis=1)

    # plot
    x, y = positions.T
    xs, ys = smoothed.T

    import matplotlib.pyplot as plt
    fig, ax = plt.subplots(1,1)
    ax.plot(x, y, 'o')
    ax.plot(xs, ys, 'k-', alpha=0.3, lw=2)
    plt.show()

demo()