【问题标题】:Python Pandas: Search rows with consecutive conditionPython Pandas:搜索具有连续条件的行
【发布时间】:2019-10-25 15:47:59
【问题描述】:

我有一个如下的数据框:

Text  Label 
 a     NaN
 b     NaN
 c     NaN
 1     NaN
 2     NaN
 b     NaN
 c     NaN 
 a     NaN
 b     NaN
 c     NaN

每当模式“a,b,c”向下出现时,我想将该部分标记为字符串,例如“检查”。最终数据框应如下所示:

Text  Label 
 a     Check
 b     Check
 c     Check
 1     NaN
 2     NaN
 b     NaN
 c     NaN 
 a     Check
 b     Check
 c     Check

最好的方法是什么。谢谢=)

【问题讨论】:

    标签: python pandas


    【解决方案1】:

    这是一个利用广播的基于NumPy 的方法:

    import numpy as np
    
    w = df.Text.cumsum().str[-3:].eq('abc') # inefficient for large dfs
    m = (w[w].index.values[:,None] + np.arange(-2,1)).ravel()
    df.loc[m, 'Label'] = 'Check'
    
       Text  Label
    0    a  Check
    1    b  Check
    2    c  Check
    3    1    NaN
    4    2    NaN
    5    b    NaN
    6    c    NaN
    7    a  Check
    8    b  Check
    9    c  Check
    

    【讨论】:

      【解决方案2】:

      使用this 解决方案和numpy.where 作为一般解决方案:

      arr = df['Text']
      pat = list('abc')
      N = len(pat)
      def rolling_window(a, window):
          shape = a.shape[:-1] + (a.shape[-1] - window + 1, window)
          strides = a.strides + (a.strides[-1],)
          c = np.lib.stride_tricks.as_strided(a, shape=shape, strides=strides)
          return c
      
      b = np.all(rolling_window(arr, N) == pat, axis=1)
      c = np.mgrid[0:len(b)][b]
      
      d = [i  for x in c for i in range(x, x+N)]
      df['label'] = np.where(np.in1d(np.arange(len(arr)), d), 'Check', np.nan)
      print (df)
        Text  Label  label
      0    a    NaN  Check
      1    b    NaN  Check
      2    c    NaN  Check
      3    1    NaN    nan
      4    2    NaN    nan
      5    b    NaN    nan
      6    c    NaN    nan
      7    a    NaN  Check
      8    b    NaN  Check
      9    c    NaN  Check
      

      【讨论】:

        【解决方案3】:

        旧的 shiftbfill 也可以工作(对于少量步骤):

        s = df.Text.eq('c') & df.Text.shift().eq('b') & df.Text.shift(2).eq('a')
        df.loc[s, 'Label'] = 'Check'
        df.Label.bfill(limit=2, inplace=True)
        

        输出:

          Text  Label
        0    a  Check
        1    b  Check
        2    c  Check
        3    1    NaN
        4    2    NaN
        5    b    NaN
        6    c    NaN
        7    a  Check
        8    b  Check
        9    c  Check
        

        【讨论】:

          猜你喜欢
          • 2021-11-12
          • 2016-08-15
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          相关资源
          最近更新 更多