加速使用前一行结果的行操作

时间:2017-10-01 13:43:32

标签: python python-2.7 pandas numpy numba

我从一个accelorometer获得了一些数据,我试图平滑这些值。我遇到的问题是我的数据框包含大约。因此,下面显示的1,000,000行并运行平滑功能需要几分钟(我在jupyter中运行它)

def smoothing(df, alpha, length):
    df['x'][0] = df['x'][0] * alpha

    for i in range(1,length):
        df['x'][i] = df['x'][i-1]+alpha*(df['x'][i] - df['x'][i-1])

    return df

我的问题是,无论如何通过使用矢量化,pandas.apply或类似方法来增强或加速此计算。请注意,我自己尝试过使用这些方法,但没有任何运气,因为我未能产生正确的结果。我努力的部分是获得前一行的结果,我不确定如何例如使用.shift()来获得与 smoothing 函数

相同的功能

以下是一些示例数据:

x_list = [21,42,49,8,0,-57,-137, -135,-177, -181]
data = pd.DataFrame(x_list, columns=['x'])
smoothing(data, 0.02, len(x_list))

预期结果:

    x
0   0
1   0
2   0
3   0
4   0
5  -1
6  -3
7  -5
8  -8
9 -11

2 个答案:

答案 0 :(得分:2)

您可以在全局变量的帮助下使用apply来存储计算值以获得所需的输出,即

store = 0
def m(x):
    global store 
    if x == data['x'][0]:
        store = 0.2*x
        return store
    else :     
        store = (store+alpha*(x - store))
        return store    

data['x'].apply(m)

输出:

0     4.200000
1    11.760000
2    19.208000
3    16.966400
4    13.573120
5    -0.541504
6   -27.833203
7   -49.266563
8   -74.813250
9   -96.050600
Name: x, dtype: float64
%%timeit
data['x'].apply(m)
1000 loops, best of 3: 478 µs per loop

n = pd.concat([data['x']]*10000).reset_index(drop=True) # in function condtion shld be n[0] instead of data['x'][0]
n.apply(m)
1 loop, best of 3: 2.18 s per loop

答案 1 :(得分:2)

这是numba方式,它比OP中的功能快得多(10,000行快约20,000倍,并且不是错字!):

from numba import njit

@njit
def smoothing_numba(x,alpha):
    x[0] = x[0] * alpha

    for i in range(1,len(x)):
        x[i] = x[i-1] + alpha * ( x[i] - x[i-1] )

    return x

smoothing_numba(data.x.values,0.02)

如果您将@njit装饰器从上述代码中删除,则您将拥有标准的numpy功能。结果比numba慢约150倍,但仍比原始功能快150倍。

以下是10,000行的时间。

np.random.seed(123)
data = pd.DataFrame(np.random.randn(10000), columns=['x'])

%timeit smoothing(data, 0.02, len(data))
1 loop, best of 3: 995 ms per loop

%timeit smoothing_numba(data.x.values, 0.02)
10000 loops, best of 3: 41.8 µs per loop

在这样的情况下,循环是不可避免的,从将pandas函数转换为numpy / numba函数看到显着的加速肯定并不罕见。另请注意,numba设计为与numpy配合使用,因此一旦将函数从pandas转换为numpy,使用@njit进行装饰以增加速度通常是微不足道的。