如何根据多个条件从numpy数组中删除行?

时间:2014-08-19 09:42:58

标签: python arrays numpy

我有一个包含4列和数千行的文件。我想删除第一列中的项目在特定范围内的行。例如, 如果我的文件中的数据如下:

18  6.215   0.025
19  6.203   0.025
20  6.200   0.025
21  6.205   0.025
22  6.201   0.026
23  6.197   0.026
24  6.188   0.024
25  6.187   0.023
26  6.189   0.021
27  6.188   0.020
28  6.192   0.019
29  6.185   0.020
30  6.189   0.019
31  6.191   0.018
32  6.188   0.019
33  6.187   0.019
34  6.194   0.021
35  6.192   0.024
36  6.193   0.024
37  6.187   0.026
38  6.184   0.026
39  6.183   0.027
40  6.189   0.027

我想删除第一项介于20到25之间或介于30和35之间的行。这意味着我期望的输出是:

18  6.215   0.025
19  6.203   0.025
26  6.189   0.021
27  6.188   0.020
28  6.192   0.019
29  6.185   0.020
36  6.193   0.024
37  6.187   0.026
38  6.184   0.026
39  6.183   0.027
40  6.189   0.027

我怎么能这样做?

4 个答案:

答案 0 :(得分:7)

如果您想继续使用numpy,解决方案并不难。

data = data[np.logical_not(np.logical_and(data[:,0] > 20, data[:,0] < 25))]
data = data[np.logical_not(np.logical_and(data[:,0] > 30, data[:,0] < 35))]

或者如果您想将它们全部合并到一个语句中,

data = data[
    np.logical_not(np.logical_or(
        np.logical_and(data[:,0] > 20, data[:,0] < 25),
        np.logical_and(data[:,0] > 30, data[:,0] < 35)
    ))
]

为了解释,像data[:,0] < 25这样的条件语句创建了布尔数组,它们逐个元素地跟踪数组中的条件为true或false。在这种情况下,它会告诉您第一列数据的小于25的位置。

您还可以使用这些布尔数组索引numpy数组。像data[data[:,0] > 30]之类的语句会提取data[:,0] > 30为真的所有行,或者第一个元素大于30的所有行。这种条件索引是提取行(或列,或者你想要的那些元素。

最后,我们需要逻辑工具来逐元素地组合布尔数组。常规andornot语句不起作用,因为它们尝试将布尔数组作为一个整体组合在一起。幸运的是,numpy提供了一组这些工具,可以np.logical_andnp.logical_ornp.logical_not的形式使用。有了这些,我们可以按元素方式组合我们的布尔数组,以找到满足更复杂条件的行。

答案 1 :(得分:2)

在特殊但频繁的情况下,选择标准是值是否达到一个区间,我使用差异的abs()到区间的中间,特别是如果midInterval具有物理意义:

data = data[abs(data[:,0] - midInterval) < deviation] # '<' for keeping the interval

如果数据类型是整数且中间值不是(如Jun的请求中),则可以将值加倍而不是转换为float(对于大整数,舍入错误变为> 1):

data = data[abs(2*data[:,0] - sumOfLimits) > deltaOfLimits]

重复以删除两个间隔。在Jun的问题中有限制:

data = data[abs(2*data[:,0] - 45) > 3]
data = data[abs(2*data[:,0] - 65) > 3]

答案 2 :(得分:1)

在下面找到我对numpy数组中删除特定行问题的解决方案。该解决方案以单行形式提供:

#  Remove the rows whose first item is between 20 and 25
A = np.delete(A, np.where( np.bitwise_and( (A[:,0]>=20), (A[:,0]<=25) ) )[0], 0)

并且基于纯numpy函数(np.bitwise_and,np.where,np.delete)。

A = np.array( [   [ 18, 6.215, 0.025 ],
    [ 19, 6.203, 0.025 ],
    [ 20, 6.200, 0.025 ],
    [ 21, 6.205, 0.025 ],
    [ 22, 6.201, 0.026 ],
    [ 23, 6.197, 0.026 ],
    [ 24, 6.188, 0.024 ],
    [ 25, 6.187, 0.023 ],
    [ 26, 6.189, 0.021 ],
    [ 27, 6.188, 0.020 ],
    [ 28, 6.192, 0.019 ],
    [ 29, 6.185, 0.020 ],
    [ 30, 6.189, 0.019 ],
    [ 31, 6.191, 0.018 ],
    [ 32, 6.188, 0.019 ],
    [ 33, 6.187, 0.019 ],
    [ 34, 6.194, 0.021 ],
    [ 35, 6.192, 0.024 ],
    [ 36, 6.193, 0.024 ],
    [ 37, 6.187, 0.026 ],
    [ 38, 6.184, 0.026 ],
    [ 39, 6.183, 0.027 ],
    [ 40, 6.189, 0.027 ] ] )

#  Remove the rows whose first item is between 20 and 25
A = np.delete(A, np.where( np.bitwise_and( (A[:,0]>=20), (A[:,0]<=25) ) )[0], 0)

# Remove the rows whose first item is between 30 and 35
A = np.delete(A, np.where( np.bitwise_and( (A[:,0]>=30), (A[:,0]<=35) ) )[0], 0)

>>> A
array([[  1.80000000e+01,   6.21500000e+00,   2.50000000e-02],
       [  1.90000000e+01,   6.20300000e+00,   2.50000000e-02],
       [  2.60000000e+01,   6.18900000e+00,   2.10000000e-02],
       [  2.70000000e+01,   6.18800000e+00,   2.00000000e-02],
       [  2.80000000e+01,   6.19200000e+00,   1.90000000e-02],
       [  2.90000000e+01,   6.18500000e+00,   2.00000000e-02],
       [  3.60000000e+01,   6.19300000e+00,   2.40000000e-02],
       [  3.70000000e+01,   6.18700000e+00,   2.60000000e-02],
       [  3.80000000e+01,   6.18400000e+00,   2.60000000e-02],
       [  3.90000000e+01,   6.18300000e+00,   2.70000000e-02],
       [  4.00000000e+01,   6.18900000e+00,   2.70000000e-02]])

答案 3 :(得分:-1)

为此,您不需要为numpy添加复杂性。 我猜你正在把你的文件读入这里的列表列表(每行都是整个数据列表中的列表,如下所示:((18,6.215,0.025),(19,6.203,0.025),. ..))。 在这种情况下使用以下规则:

for row in data:
    if((row[0] > 20 and row[0] < 25) or (row[0] > 30 and row[0] < 35)):
        data.remove(row)