롤링 팬더의 속도를 높입니다.

5712 단어 pythonpandas
Pandas는 파이썬에서 데이터 분석에 매우 유용한 패키지이며 일반적으로 매우 성능이 좋습니다. 그러나 성능 향상이 중요할 수 있는 경우가 있습니다.
아래에서는 numpy를 사용하여 더 빠른 버전의 롤링 창을 만드는 방법을 살펴봅니다.

다음 스니펫을 고려하십시오.

import pandas as pd
import numpy as np
s = pd.Series(range(10**6))
s.rolling(window=2).mean()


롤링 호출은 크기가 2인 창을 만든 다음 각각의 평균을 계산합니다.

0 NaN
1 0.5
2 1.5
 …
999998 999997.5
999999 999998.5
Length: 1000000, dtype: float64


그러나 numpy에서 stride_tricks를 사용하면 값을 더 빠르게 반복하는 함수를 만들 수 있습니다.

def rolling_window(a, window):
    shape = a.shape[:-1] + (a.shape[-1] - window + 1, window)
    strides = a.strides + (a.strides[-1],)
    return np.lib.stride_tricks.as_strided(a, shape=shape, strides=strides)


(참고: scikit-image에 이 함수의 버전이 있습니다.from skimage.util.shape import view_as_windows )

다음과 같이 새로운 롤링_윈도우 함수를 사용할 수 있습니다.np.mean(rolling_window(s,2), axis=1)
이것은 pandas의 롤링() 메서드를 사용하여 계산한 것과 동일한 데이터를 반환하지만 선행 nan 값은 포함하지 않습니다.

성능 측정



%timeit 도구(편리하게 Ipython에 내장되어 있으므로 jupyter에도 있음)를 사용하여 두 버전의 성능을 측정합니다.

s = pd.Series(np.random.randint(10, size=10**6))
%timeit s.rolling(window=2).mean()
%timeit np.mean(rolling_window(s, 2), axis=1)


출력:

58.6 ms ± 1.42 ms per loop (mean ± std. dev. of 7 runs, 10 loops each)
25.1 ms ± 1.24 ms per loop (mean ± std. dev. of 7 runs, 10 loops each)


numpy 버전은 약 두 배 빠릅니다. 다른 크기의 어레이의 경우 성능이 2~5배 더 빠릅니다.
다시 확인해 보겠습니다. 하지만 다른 계산으로:

s = pd.Series(np.random.randint(10, size=10**6))
%timeit s.rolling(window=2).sum()
%timeit np.sum(rolling_window(s, 2), axis=1)


출력:

52.5 ms ± 1.73 ms per loop (mean ± std. dev. of 7 runs, 10 loops each)
14.9 ms ± 129 µs per loop (mean ± std. dev. of 7 runs, 100 loops each)


그게 다야. 상당한 속도 향상을 위해 약간의 가독성을 희생했습니다.

메모
위의 버전보다 더 빠르게 평균을 계산하는 방법에는 여러 가지가 있습니다. 성능을 정말로 찾고 있다면 이 요지에서 노트북을 참조하십시오: rolling.ipynb

좋은 웹페이지 즐겨찾기