Python 如何计算熊猫最长不间断序列
比如说,我有Python 如何计算熊猫最长不间断序列,python,pandas,Python,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() cou
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
,但在所有True
的系列中,它将打印0
选项1
使用序列本身的一个符号来掩盖否定的累积和。然后使用值\u计数
(~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
s表示,其中有四个。这是因为组是由第一个False
(通过(~s)
)启动的。因此,我们用我们开始使用的布尔掩码来屏蔽这个累积和
(~s).cumsum()[s]
1 1
3 2
4 2
5 2
dtype: int64
现在我们看到三个2
s弹出,我们只需要使用一种方法来提取它们。我使用了value\u计数
和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
我不太清楚如何使用熊猫,但是使用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
编辑:正如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()
(如果最长的True
如piRSquared所指出的从开头开始或结尾结束,这将不会给出正确答案。请使用piRSquared给出的上述解决方案。此工作仅用于解释。)
说明:
这会找到False
部分的索引,通过查找False
索引之间的间隙,我们可以知道最长的True
s.where(s==False).dropna().index.values
查找False
array([0, 2, 6, 7])
我们知道True
s生活在False
s之间。因此,我们可以使用
np.diff
查找这些指数之间的差距
array([2, 4, 1])
- 最后减1,因为
True
s位于这些索引之间
- 找出差异的最大值
我认为这是可行的
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-answer启发):
使用lambda func执行此操作的另一个选项
s.to_frame().apply(lambda x: s.loc[x.name:].idxmin() - x.name, axis=1).max()
Out[429]: 3
您的代码实际上非常接近。它通过一个小补丁变得完美:
count = 0
maxCount = 0
for item in s:
if item:
count += 1
if count > maxCount:
maxCount = count
else:
count = 0
print(maxCount)
谢谢你的精彩解释。伙计,这真是太棒了:-)@piRSquared添加了一个python groupby:-)干杯:-),从你那里学到了很多,谢谢你,先生@piRSquared,谢谢,并学会了使用(~a).cumsum()的新技巧@piRSquared,我如何知道最长的True序列出现在哪里?嗯,很好的解决方案,这很好。但是,如果在数组的开头或结尾有最长的True
序列,则diff将无法捕获它。您需要在末尾追加False
,然后执行此操作。另外,您不需要s==False
,~s
就可以了。这就是我应该做的。如果你想(-:(np.diff(np.flatnonzero(np.append(True,np.append(~s.values,True)))-1.max()
,请随意将其添加到你的答案中,因为这是一个相同的概念。不过我建议格式更好。@piRSquared感谢你提供了解决方案。我很感激。这非常干净。@wen,很好地使用了s.index[~s]也许我需要花更多的时间来学习python标准库。如果所有元素都是False
,它将返回8
,因此代码应该是max([len(list(group))表示键,groupby中的group(s.tolist())表示键。)
count = 0
maxCount = 0
for item in s:
if item:
count += 1
if count > maxCount:
maxCount = count
else:
count = 0
print(maxCount)