熊猫最大滚动的数字版本

时间:2019-05-20 03:10:12

标签: python pandas performance numpy rolling-computation

TL; DR:我的问题是我该如何改善我的功能以胜过熊猫自己的最大移动功能?


背景信息:

因此,我正在处理许多移动平均值,最大移动量和最小移动量等,到目前为止,我发现的唯一移动窗口(例如要素)位于pandas.rolling method中。问题是:我拥有的数据是numpy数组,而我想要的最终结果也必须在numpy数组中;我想将其简单地转换为pandas系列并返回numpy array来完成以下工作:

result2_max = pd.Series(data_array).rolling(window).max().to_numpy()

,这太不合常规了,因为转换数据类型似乎是不必要的,并且可能存在纯粹在numpy实现中做完全相同的事情的方法。

但是,尽管看起来很不可思议,但它比我在网上提出或看到的任何方法都快。我将在下面给出一些小基准:

import numpy as np
import pandas as pd

def numpy_rolling_max(data, window):

    data = data[::-1]
    data_strides = data.strides[0]

    movin_window = np.lib.stride_tricks.as_strided(data, 
                                                    shape=(data.shape[0] - window +1, window), 
                                                    strides = (data_strides ,data_strides)
                                                    )[::-1]
    max_window =np.amax(movin_window, axis = 1)#this line seems to be the bottleneck


    nan_array = np.full(window - 1, np.nan)
    return np.hstack((nan_array, max_window))


def pandas_rolling_max(data, window):
    return pd.Series(data).rolling(window).max().to_numpy()

length = 120000
window = 190
data = np.arange(length) + 0.5

result1_max = numpy_rolling_max(data, window)#21.9ms per loop
result2_max = pandas_rolling_max(data, window)#5.43ms per loop

result_comparision = np.allclose(result1_max, result2_max, equal_nan = True)

在arraysize = 120k,window = 190的情况下,大熊猫滚动最大值比numpy版本快约3倍。我不知道从哪里开始,因为我已经尽可能地向量化了自己的函数,但是它仍然比熊猫版本慢很多,我也不知道为什么。

提前谢谢

编辑:我已经找到了瓶颈,它就是这一行:

max_window =np.amax(movin_window, axis = 1)

但是看到它已经是向量化函数调用,我仍然不知道如何进行。

1 个答案:

答案 0 :(得分:3)

我们可以使用1D max filter from Scipy来复制与 // serverMessage: string; No need anymore serverMessage$: Observable<string>; constructor( private cs: CommonService ) { this.serverMessage$ = this.cs.serverMessage$ .pipe(scan((accumaltor, message) => accumator + message)) // .subscribe((message: string) => { // this.serverMessage += message; // }); // No need to subscribe anymore as we will be using the `async pipe`, but if you need `serverMessage` for something else // You can remove the comments and make it `=` not `+=` as the messages are already concatinated } 相同的行为,并且仍然会更加有效-


<!-- notice the async pipe here, remove the need to unsubscribe() at ngDestroy() -->
<div class="col-md-12" *ngIf="serverMessage$ | async as serverMessage">
    <textarea style="width: 100%" cols="50" rows="10">{{ serverMessage }}</textarea>
</div>

样品运行-

pandas

关于实际测试用例大小的计时-

from scipy.ndimage.filters import maximum_filter1d

def max_filter1d_same(a, W, fillna=np.nan):
    out_dtype = np.full(0,fillna).dtype
    hW = (W-1)//2 # Half window size
    out = maximum_filter1d(a,size=W, origin=hW)
    if out.dtype is out_dtype:
        out[:W-1] = fillna
    else:
        out = np.concatenate((np.full(W-1,fillna), out[W-1:]))
    return out