簡體   English   中英

如何計算熊貓中最長的不間斷序列

[英]How to count longest uninterrupted sequence in pandas

假設我有pd.Series如下

s = pd.Series([False, True, False,True,True,True,False, False])    

0    False
1     True
2    False
3     True
4     True
5     True
6    False
7    False
dtype: bool

我想知道最長的True序列有多長,在本例中,它是3。

我以一種愚蠢的方式嘗試過它。

s_list = s.tolist()
count = 0
max_count = 0
for item in s_list:
    if item:
        count +=1
    else:
        if count>max_count:
            max_count = count
        count = 0
print(max_count)

它將打印3 ,但在Series的全部True ,它將打印0

選項1
使用系列本身來掩蓋否定的累積和。 然后使用value_counts

(~s).cumsum()[s].value_counts().max()

3

說明

  1. (~s).cumsum()是一種非常標准的方法來產生不同的True / False

     0 1 1 1 2 2 3 2 4 2 5 2 6 3 7 4 dtype: int64 
  2. 但你可以看到我們關心的群體由2秒代表,其中有4個。 這是因為該組由第一個False啟動(隨着(~s)變為True )。 因此,我們使用我們開始使用的布爾掩碼來掩蓋此累積和。

     (~s).cumsum()[s] 1 1 3 2 4 2 5 2 dtype: int64 
  3. 現在我們看到三個2彈出,我們只需要使用一個方法來提取它們。 我使用了value_countsmax


選項2
使用factorizebincount

a = s.values
b = pd.factorize((~a).cumsum())[0]
np.bincount(b[a]).max()

3

說明
這與選項1的解釋類似。主要區別在於我如何找到最大值。 我使用pd.factorize將值標記為整數,范圍從0到唯一值的總數。 鑒於我們在(~a).cumsum()的實際值,我們並不嚴格需要這部分。 我使用它是因為它是一個可用於任意組名的通用工具。

pd.factorize我在使用這些整數值np.bincount積聚的次使用每個整數總數。 然后取最大值。


選項3
如選項2的說明中所述,這也有效:

a = s.values
np.bincount((~a).cumsum()[a]).max()

3

我認為這可行

pd.Series(s.index[~s].values).diff().max()-1
Out[57]: 3.0

在熊貓外面,我們可以回到python groupby

from itertools import groupby
max([len(list(group)) for key, group in groupby(s.tolist())])
Out[73]: 3

更新:

from itertools import compress
max(list(compress([len(list(group)) for key, group in groupby(s.tolist())],[key for key, group in groupby(s.tolist())])))
Out[84]: 3

編輯 :正如piRSquared所提到的,我之前的解決方案需要在系列的開頭和結尾添加兩個False piRSquared在此基礎上給出了答案。

(np.diff(np.flatnonzero(np.append(True, np.append(~s.values, True)))) - 1).max()

我最初的試用版是

(np.diff(s.where(~s).dropna().index.values) - 1).max()

(如果piRSquared指出,如果最長的True在開始時開始或在結束時結束, 則不會給出正確的答案請使用piRSquared給出的上述解決方案。這項工作僅用於解釋。)

說明:

這找到了False部分的索引, 通過找到False索引之間的間隙,我們可以知道最長的True

  • s.where(s == False).dropna().index.values查找False所有索引

     array([0, 2, 6, 7]) 

我們知道True的生活在False之間。 因此,我們可以使用np.diff來找到這些索引之間的差距。

    array([2, 4, 1])
  • 最后減1,因為True s位於這些指數之間。

  • 找出差異的最大值。

你可以使用(靈感來自@piRSquared的回答):

s.groupby((~s).cumsum()).sum().max()
Out[513]: 3.0

使用lambda函數執行此操作的另一個選項。

s.to_frame().apply(lambda x: s.loc[x.name:].idxmin() - x.name, axis=1).max()
Out[429]: 3

我不太確定如何使用pandas但是如何使用itertools.groupby

>>> import pandas as pd
>>> s = pd.Series([False, True, False,True,True,True,False, False])
>>> max(sum(1 for _ in g) for k, g in groupby(s) if k)
3

你的代碼實際上非常接近。 它通過一個小修復變得完美:

count = 0
maxCount = 0
for item in s:
    if item:
        count += 1
        if count > maxCount:
            maxCount = count
    else:
        count = 0
print(maxCount)

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM