如何计算熊猫中最长的不间断序列

时间:2018-02-21 02:26:08

标签: 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()
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的{​​{1}}中,它会打印True

6 个答案:

答案 0 :(得分:8)

选项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代表,其中有四个。这是因为该群组是由第一个False启动的(True(~s)成为(~s).cumsum()[s] 1 1 3 2 4 2 5 2 dtype: int64 。因此,我们使用我们开始的布尔掩码来掩盖这个累积和。

    2
  3. 现在我们看到三个value_counts弹出,我们只需要使用一种方法来提取它们。我使用了maxfactorize

  4. 选项2
    使用bincounta = s.values b = pd.factorize((~a).cumsum())[0] np.bincount(b[a]).max() 3

    pd.factorize

    <强>解释
    这与选项1的解释类似。主要区别在于我如何找到最大值。我使用(~a).cumsum()将值标记为整数,范围从0到唯一值的总数。鉴于我们在pd.factorize中的实际值,我们并不严格需要这部分。我使用它是因为它是一个可用于任意组名的通用工具。

    np.bincount之后,我使用a = s.values np.bincount((~a).cumsum()[a]).max() 3 中的那些整数值,它累计了每个整数的总次数。然后取最大值。

    选项3
    如选项2的解释所述,这也有效:

    package main;
    
    import org.openqa.selenium.*;
    
    public class SitePoster {
    
        public static void main(String[] args) {
             //System.setProperty("webdriver.chrome.driver", "./pathtodriver");
            WebDriver driver = new ChromeDriver();
            //Getting error saying "ChromeDriver can't be resolved to a type"
        } 
    
    }
    

答案 1 :(得分:4)

我认为这可以起作用

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

答案 2 :(得分:2)

编辑:正如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之间存在False。因此,我们可以使用 np.diff找出这些指数之间的差距。

    array([2, 4, 1])
  • 最后减1,因为True位于这些指数之间。

  • 找出差异的最大值。

答案 3 :(得分:2)

你可以使用(灵感来自@piRSquared答案):

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

使用lambda func执行此操作的另一个选项。

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

答案 4 :(得分:1)

我不确定如何使用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

答案 5 :(得分:1)

你的代码实际上非常接近。通过一个小修复它变得完美:

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