2015-06-09 75 views
2

我有以下的熊貓系列(表示爲列表):如何計算熊貓系列中前一個零點的距離?

[7,2,0,3,4,2,5,0,3,4] 

我想定義一個新的系列,返回到最後零距離。這意味着,我想有以下輸出:

[1,2,0,1,2,3,4,0,1,2] 

如何做到這一點的大熊貓最有效的方法是什麼?

回答

1

看到使用Cython來獲得這種東西的c-like速度有多簡單,這有時讓人驚訝。假設你列的.valuesarr,則:

cdef int[:, :, :] arr_view = arr 
ret = np.zeros_like(arr) 
cdef int[:, :, :] ret_view = ret 

cdef int i, zero_count = 0 
for i in range(len(ret)): 
    zero_count = 0 if arr_view[i] == 0 else zero_count + 1 
    ret_view[i] = zero_count 

注意使用typed memory views,這是非常快。您可以使用此功能使用@cython.boundscheck(False)進行進一步加速。

4

在大熊貓一種解決方案是一個有點棘手,但看起來是這樣的(s是您的系列):

>>> x = (s != 0).cumsum() 
>>> y = x != x.shift() 
>>> y.groupby((y != y.shift()).cumsum()).cumsum() 
0 1 
1 2 
2 0 
3 1 
4 2 
5 3 
6 4 
7 0 
8 1 
9 2 
dtype: int64 

對於最後一個步驟,這裏採用的大熊貓「itertools.groupby」食譜食譜here

+0

我欣賞優雅,但這執行大量遍+一個''GROUPBY ',對於那些在單遍Cython擴展中如此微不足道的東西。 –

+0

我同意 - 如果性能很重要,這種類型的東西在Cython中實現會更好。在Pandas中可以做到這一點(如食譜所示),如果Cython不是可用的選項,這很方便。 –

5

複雜度爲O(n)。什麼會減慢它在Python中執行for循環。如果有k零在系列,和log k是negligibile比較序列的長度,一個O(n log k)的解決辦法是:

>>> izero = np.r_[-1, (ts == 0).nonzero()[0]] # indices of zeros 
>>> idx = np.arange(len(ts)) 
>>> idx - izero[np.searchsorted(izero - 1, idx) - 1] 
array([1, 2, 0, 1, 2, 3, 4, 0, 1, 2])