【问题标题】:Are there some efficient ways to find row(s) meeted conditons which referred to the values in next some rows?是否有一些有效的方法来查找行)满足引用下一些行中的值的条件?
【发布时间】:2019-07-31 01:53:01
【问题描述】:

我想寻找有效的方法来查找满足数据框中某些条件的行。 数据框有 n 行和 3 列。值为-101
我想找到满足两个条件的行。

  1. 条件:行的值(row0) !=-1;
  2. 条件:接下来3行(row1,row2,row3)生成的数组的对角线=1。

我使用循环方法遍历所有行并找到满足条件的行。但是,这不是一种有效的方法,尤其是当有一个大数据框并且这一步只是第一步时。

# Given a dataframe (n*3) 

randNum=random.choices(range(-1,2),k=333) # k=3*int
frame=pd.DataFrame(np.array(randNum).reshape(-1,3))

# its values = -1,0,1, like this:
# In [126]:frame
# Out[126]:
#     0  1  2
# 0    1  0  0
# 1    1 -1  1
# 2    1  1  1
# 3   -1 -1  1
# 4   -1  0 -1
# 5    1  1 -1
# ...
# 105 -1 -1 -1
# 106 -1 -1  0
# 107 -1 -1  0
# 108  0 -1  1
# 109 -1  0  1
# 110  1  0  1
#  I want find the row(s) that all of the values of
#  columns('0','1','2')!=-1, and while the value of 
#  the diagonal of next three rows =1, like this:
#       0  1  2
# row0  v1 v2 v3     # v1!=v2!=v3!=-1, it may be 1 or 0.
# row1   1  v  v
# row2   v  1  v          # v =-1 or 0 or 1
# row3   v  v  1
# the diagonal of rows (row1,row2,row3)=1

我想在 DataFrame 中找到第 0 行。它可以通过循环方法解决,但是否存在有效的解决方案?非常感谢!

【问题讨论】:

    标签: python python-3.x pandas numpy dataframe


    【解决方案1】:

    您可以使用布尔掩码来表示每个单独的条件。第一个很简单:

    c1_mask = frame[0] != -1
    
    # edited version:
    c1_mask = (frame!=-1).all(axis=1)
    

    第二个可以通过卷积运算解决

    from scipy.signal import convolve2d
    
    c2_mask = convolve2d(frame.values, np.eye(3), mode='valid')
    c2_mask = (np.vstack([c2_mask, np.zeros((3, 1))]) == 3).reshape(-1)
    
    # edited version:
    c2_kernal = np.vstack((np.zeros((1,3)), np.eye(3)))
    c2_mask = convolve2d(frame.values, c2_kernal, mode='valid')
    c2_mask = (c2_mask == 3).reshape(-1)
    

    然后将它们组合起来:

    frame[c1_mask & c2_mask]
    
    # edited version:
    (frame[:-3])[(c1_mask[:-3]).shift[-1] & c2_mask]
    

    请注意,在此解决方案中,列数只是一个参数,因此可以轻松扩展。

    【讨论】:

    • 郑重声明,我真的很喜欢这个答案——卷积是解决这个问题的好方法。
    【解决方案2】:
    randNum=random.choices(range(-1,2),k=333) # k=3*int
    df=pd.DataFrame(np.array(randNum).reshape(-1,3))
    
    # `D2` represents the second diagonal (init to -100 to handle last two rows)
    # `D3` represents the third diagonal (init to -100 to handle last two rows)
    df['D2'] = df['D3'] = -100
    df['D2'][0:-1] = df[1][1:]
    df['D3'][0:-2] = df[2][2:]
    df[(df[0] != -1) & (df[1]!= -1) & (df[2] != -1) & (df[0] + df['D2'] + df['D3'] == 3)]
    

    逻辑:

    1. 对于任何行,第二个对角线值始终位于第 1 列 (D2)
    2. 对于任何行,第三个对角线值始终位于第 2 列 (D3)
    3. 现在归结为检查[0] + [D2] + [D3] == 3

    【讨论】:

    • 谢谢 mujjiga。那没起效。我认为原因可能是切片。数据帧的切片带有行标签,因此不能将 D2 分配在正确的位置。我尝试修复它,但失败了。 df.shift 可能是解决问题的方法。
    【解决方案3】:

    第一个条件:

    v1=df[df[0]=!1 & df[1]=!1 & df[2]=!1].index.tolist()
    

    第二个条件:

    v2=[]
    for i in v1:
         if df[0][i+1]==1 and df[1][i+2]==1 and df[1][i+3]==1:
             v2.append(i)
    

    查看感兴趣行的索引:

    print(v2)
    

    访问这些 df 块中的第一个:

    df.loc[[v2[0],v2[0]+1,v2[0]+2,v2[0]+3]]
    

    【讨论】:

      【解决方案4】:

      这里有很多复杂的答案。我不会做复杂的。

      df.loc[(df != -1).all(axis=1) & (df[0].shift(-1) == 1) & (df[1].shift(-2) == 1) & (df[2].shift(-3) == 1), :]
      

      【讨论】:

      • 这不是正确的布尔索引,您是否尝试运行此代码?你会得到一个TypeError
      • 没有。我用手机回答了这个问题。我添加了 perens 来修复它。
      • 感谢 CJR。我已经修好了。像这样: df.loc[((df != -1).all(axis=1) )& (df[0].shift(-1) == 1) & (df[1].shift(-2 ) == 1) & (df[2].shift(-3) == 1), :]
      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2023-03-10
      • 2021-03-22
      • 1970-01-01
      • 2011-10-07
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多