Python Pandas:获取列中有效后续帧的第一个和最后一个索引

Python Pandas:获取列中有效后续帧的第一个和最后一个索引,python,pandas,Python,Pandas,我有一个pandasDataFrame对象,它包含nans。我希望找到每个列的所有后续有效帧块,并从这些块中找到第一个和最后一个索引 示例数据: [ [ 1,nan], [ 2,nan], [ 3,nan], [ 4,3.0], [ 5,1.0], [ 6,4.0], [ 7,1.0], [ 8,5.0], [ 9,9.0], [10,2.0], [11,nan], [12,nan], [13,6.0], [14,5.0], [15,3

我有一个
pandas
DataFrame
对象,它包含nans。我希望找到每个列的所有后续有效帧块,并从这些块中找到第一个和最后一个索引

示例数据:

[
  [ 1,nan],
  [ 2,nan],
  [ 3,nan],
  [ 4,3.0],
  [ 5,1.0],
  [ 6,4.0],
  [ 7,1.0],
  [ 8,5.0],
  [ 9,9.0],
  [10,2.0],
  [11,nan],
  [12,nan],
  [13,6.0],
  [14,5.0],
  [15,3.0],
  [16,5.0]
]
其中第一列是索引,第二列是我要筛选的值。结果应该是这样的

[(4,10), (13,16)]
出于性能原因,我希望避免通过
for
-循环手动迭代数据

更新1: 另外两个标准:

  • 值列中的有效值不必相等。它们可以接受-inf和+inf之间的任何有效浮点值

  • 我只需要有效块的第一个和最后一个索引,而不需要中间的NaN块

  • 我认为你可以使用:

    #set column names and set index by first column 
    df.columns = ['idx', 'a']
    df = df.set_index('idx')
    #find groups
    df['b'] = (df.a.isnull() != df.a.shift(1).isnull()).cumsum()
    #remove NaN
    df = df[df.a.notnull()].reset_index()
    #aggregate first and last values of column idx  
    df = df['idx'].groupby(df.b).agg(['first', 'last'])
    print zip(df['first'], df['last'])
    [(4, 10), (13, 16)]
    
    然后我尝试修改以下解决方案:


    下面是一个使用Numpy的示例。不确定它与@jezrael的解决方案相比如何,但您提到性能是一项要求,因此您可以对两者进行比较

    注意:这假设您的列名为“index”和“val”

    输出:

    [(4, 10), (13, 16)]
    

    出于某种原因,这对我不起作用。这可能与我在第一次更新中提到的有效值可以接受任何有效的浮点值有关。不过还是要谢谢你!啊,对不起,我可能错过了。我已经更新了代码。而不是:a=np.where((pre==1)和np.isnan(pst))我们做的是:a=np.where(~np.isnan(pre)和np.isnan(pst))你实际上没有错过它,加维。我忘了提到它,我的例子也没有反映出unutbu编辑它之前的标准。谢谢!这个解决方案使用的是一个小加法,我无法比较实际值,但必须依赖
    df.a.isnull()!=df.a.shift(1).isnull()
    返回每个后续块的第一个和最后一个索引。但是,它还返回有效块之间NaN块的索引。“我不需要它们,现在总得想办法把它们扔掉。”@unutbu谢谢你据此编辑了我的问题。不知怎的,我更新了它,但忘记了改变数字,以反映实际的标准。
    import numpy as np
    
    pre = np.array(df['val'] - df.diff(-1)['val'])
    pst = np.array(df['val'] - df.diff(1)['val'])
    
    a = np.where(~np.isnan(pre) & np.isnan(pst))
    z = np.where(np.isnan(pre) & ~np.isnan(pst))
    output = zip(df.ix[a[0]]['index'],df.ix[z[0]]['index'])
    
    [(4, 10), (13, 16)]