【问题标题】:Incrementing contiguous positive groups in array/Series在数组/系列中增加连续的正组
【发布时间】:2018-02-22 16:14:59
【问题描述】:

假设我有一个像这样的 Pandas 系列布尔值。

vals = pd.Series([0, 0, 0, 1, 1, 1, 1, 0, 0, 1, 1, 0, 1, 1, 1]).astype(bool)

>>> vals
0     False
1     False
2     False
3      True
4      True
5      True
6      True
7     False
8     False
9      True
10     True
11    False
12     True
13     True
14     True
dtype: bool

我想把这个布尔系列变成一个系列,其中每组 1 都被正确枚举,就像这样

0     0
1     0
2     0
3     1
4     1
5     1
6     1
7     0
8     0
9     2
10    2
11    0
12    3
13    3
14    3

我怎样才能有效地做到这一点


我已经能够手动执行此操作,在 Python 级别上循环序列并递增,但这显然很慢。我正在寻找一个矢量化的解决方案——我看到this answer from unutbu 涉及在 NumPy 中拆分增加的组,并试图让它与某种cumsum 一起工作,但到目前为止还没有成功。

【问题讨论】:

    标签: python pandas numpy series


    【解决方案1】:

    你可以试试这个:

    vals.astype(int).diff().fillna(vals.iloc[0]).eq(1).cumsum().where(vals, 0)
    
    #0     0
    #1     0
    #2     0
    #3     1
    #4     1
    #5     1
    #6     1
    #7     0
    #8     0
    #9     2
    #10    2
    #11    0
    #12    3
    #13    3
    #14    3
    #dtype: int64
    

    【讨论】:

      【解决方案2】:

      这是一个 NumPy 方法 -

      def island_same_label(vals):
      
          # Get array for faster processing with NumPy tools, ufuncs
          a = vals.values
      
          # Initialize output array
          out = np.zeros(a.size, dtype=int)
      
          # Get start indices for each island of 1s. Set those as 1s
          out[np.flatnonzero(a[1:] > a[:-1])+1] = 1
      
          # In case 1st element was True, we would have missed it earlier, so add that
          out[0] = a[0]
      
          # Finally cumsum and mask out non-island regions
          np.cumsum(out, out=out)
          return pd.Series(np.where(a, out, 0))
      

      使用样本并多次平铺输入 -

      In [15]: vals=pd.Series([0, 0, 0, 1, 1, 1, 1, 0, 0, 1, 1, 0, 1, 1, 1]).astype(bool)
      
      In [16]: vals = pd.Series(np.tile(vals,10000))
      
      In [17]: %timeit Psidom_app(vals) # @Psidom's soln
          ...: %timeit Wen_app(vals) # @Wen's soln
          ...: %timeit island_same_label(vals) # Proposed in this post
          ...: 
      100 loops, best of 3: 9.53 ms per loop
      100 loops, best of 3: 13.2 ms per loop
      1000 loops, best of 3: 959 µs per loop
      

      【讨论】:

        【解决方案3】:
        m=(vals.diff().ne(0)&vals.ne(0)).cumsum()
        m[vals.eq(0)]=0
        m
        Out[235]: 
        0     0
        1     0
        2     0
        3     1
        4     1
        5     1
        6     1
        7     0
        8     0
        9     2
        10    2
        11    0
        12    3
        13    3
        14    3
        dtype: int32
        

        数据输入

        vals = pd.Series([0, 0, 0, 1, 1, 1, 1, 0, 0, 1, 1, 0, 1, 1, 1])
        

        【讨论】:

          猜你喜欢
          • 2023-03-21
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 2016-09-05
          • 2016-06-28
          • 2016-08-26
          • 2014-03-22
          • 2018-08-13
          相关资源
          最近更新 更多