【问题标题】:Check the next index column value and consecutive length of same value in pandas dataframe检查熊猫数据框中的下一个索引列值和相同值的连续长度
【发布时间】:2019-08-05 18:44:04
【问题描述】:

我想检查下一个索引列是否与前一个索引列具有相同的值,并获得连续相同的值长度。

比如下面有一个dataframe,我想得到0的连续值的长度。

    1 2 3 4 5 6 
a   1 0 0 1 1 1
b   0 0 0 1 0 0
c   1 0 1 0 1 0
d   1 1 1 1 1 1

结果:

  • a 行有两个连续的 0 值,所以长度为 2
  • b行有三个连续的0值所以长度为3
  • c行没有连续的0值所以长度为1
  • 第d行没有值0所以长度为0


此外,如果第一个索引从 0 开始,则在值 1 出现之前不要计数,并从下一个 0 开始计算长度。

  • 应用此条件,b 行的结果应为 2。

实际数据中有超过 1000000 行,所以 for 循环会花费太长时间,所以我想知道是否有办法在 pandas 或其他方式中做到这一点。

【问题讨论】:

    标签: python pandas


    【解决方案1】:

    想法是为连续计数0 创建df1 并为new1 获取maximum 值。其次它更复杂 - 获取第一个最大值的索引(这里是最大值1,所以获取第一个1的索引)并通过掩码为设置0值创建掩码,所以接下来sum首先省略仅限0 组。

    另外,如果只有0 行返回错误的输出,所以需要用多个~a.all(axis=1).values[:, None] 更改条件以防止它:

    a = df == 0
    b = a.cumsum(axis=1)
    df1 = (b-b.where(~a, axis=1).ffill(axis=1).fillna(0).astype(int))
    
    cols = np.arange(len(df.columns))
    n = np.argmax(df.values, axis=1)[:, None]
    
    mask = (cols > n) * ~a.all(axis=1).values[:, None]
    
    df['new1'] = df1.max(axis=1)
    df['new2'] = df1.where(mask, 0).max(axis=1)
    print (df)
       1  2  3  4  5  6  new1  new2
    a  1  0  0  1  1  1     2     2
    b  0  0  0  1  0  0     3     2
    c  1  0  1  0  1  0     1     1
    d  1  1  1  1  1  1     0     0
    

    详情

    print (df1)
       1  2  3  4  5  6
    a  0  1  2  0  0  0
    b  1  2  3  0  1  2
    c  0  1  0  1  0  1
    d  0  0  0  0  0  0
    
    print (df1.where(mask, 0))
       1  2  3  4  5  6
    a  0  1  2  0  0  0
    b  0  0  0  0  1  2
    c  0  1  0  1  0  1
    d  0  0  0  0  0  0
    

    仅使用 0 行验证解决方案:

    print (df)
       1  2  3  4  5  6
    a  1  0  0  1  1  1
    b  0  0  0  0  0  0 <- only 0 row
    c  1  0  1  0  1  0
    d  1  1  1  1  1  1
    
    a = df == 0
    b = a.cumsum(axis=1)
    df1 = (b-b.where(~a, axis=1).ffill(axis=1).fillna(0).astype(int))
    
    cols = np.arange(len(df.columns))
    n = np.argmax(df.values, axis=1)[:, None]
    
    print (df1)
       1  2  3  4  5  6
    a  0  1  2  0  0  0
    b  1  2  3  4  5  6 <- count all 0
    c  0  1  0  1  0  1
    d  0  0  0  0  0  0
    
    print (df1.where(mask, 0))
       1  2  3  4  5  6
    a  0  1  2  0  0  0
    b  0  0  0  0  0  0 <- correct not count this row
    c  0  1  0  1  0  1
    d  0  0  0  0  0  0
    

    【讨论】:

    • 太棒了。结果正是我一直在寻找并了解使用 where 和 mask 的新想法。
    猜你喜欢
    • 2020-12-08
    • 2012-11-05
    • 1970-01-01
    • 1970-01-01
    • 2013-02-03
    • 1970-01-01
    • 1970-01-01
    • 2020-12-01
    • 2014-06-26
    相关资源
    最近更新 更多