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)