[英]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
說明
(~s).cumsum()
是一種非常標准的方法來產生不同的True
/ False
組
0 1 1 1 2 2 3 2 4 2 5 2 6 3 7 4 dtype: int64
但你可以看到我們關心的群體由2
秒代表,其中有4個。 這是因為該組由第一個False
啟動(隨着(~s)
變為True
)。 因此,我們使用我們開始使用的布爾掩碼來掩蓋此累積和。
(~s).cumsum()[s] 1 1 3 2 4 2 5 2 dtype: int64
現在我們看到三個2
彈出,我們只需要使用一個方法來提取它們。 我使用了value_counts
和max
。
選項2
使用factorize
和bincount
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.