python通过一大块数据过滤二维数组

标签 python arrays numpy

import numpy as np

data = np.array([
    [20,  0,  5,  1],
    [20,  0,  5,  1],
    [20,  0,  5,  0],
    [20,  1,  5,  0],
    [20,  1,  5,  0],
    [20,  2,  5,  1],
    [20,  3,  5,  0],
    [20,  3,  5,  0],
    [20,  3,  5,  1],
    [20,  4,  5,  0],
    [20,  4,  5,  0],
    [20,  4,  5,  0]
])

我有以下二维数组。让我们按上述顺序调用字段 a、b、c、d,其中 b 列类似于 id。我希望删除所有在 d 列中没有 atlist 1 出现数字“1”的单元格,因为 b 列中具有相同数字的所有单元格(相同的 id)所以过滤后我将得到以下结果:

[[20  0  5  1]
 [20  0  5  1]
 [20  0  5  0]
 [20  2  5  1]
 [20  3  5  0]
 [20  3  5  0]
 [20  3  5  1]]

所有具有b = 1b = 4 的行都已从数据中删除

总结一下,因为我看到不合适的答案。我们通过 b 列查看数据 block 。如果一个完整的数据 block 在 d 列中甚至没有一次出现数字“1”,我们将删除该 b 项的所有行。在下面的示例中,我们可以看到具有 0 次出现的 b = 1b = 4(“id”= 1 和“id”= 4)的数据 block d 列中的数字“1”。这就是它从数据中删除的原因

最佳答案

通用方法:这是一种使用 np.unique 的方法和 np.bincount解决一般情况 -

unq,tags = np.unique(data[:,1],return_inverse=1)
goodIDs = np.flatnonzero(np.bincount(tags,data[:,3]==1)>=1)
out = data[np.in1d(tags,goodIDs)]

sample 运行-

In [15]: data
Out[15]: 
array([[20, 10,  5,  1],
       [20, 73,  5,  0],
       [20, 73,  5,  1],
       [20, 31,  5,  0],
       [20, 10,  5,  1],
       [20, 10,  5,  0],
       [20, 42,  5,  1],
       [20, 54,  5,  0],
       [20, 73,  5,  0],
       [20, 54,  5,  0],
       [20, 54,  5,  0],
       [20, 31,  5,  0]])

In [16]: out
Out[16]: 
array([[20, 10,  5,  1],
       [20, 73,  5,  0],
       [20, 73,  5,  1],
       [20, 10,  5,  1],
       [20, 10,  5,  0],
       [20, 42,  5,  1],
       [20, 73,  5,  0]])

具体情况做法:如果第二列数据一直是排序的,并且有从0开始的序号,我们可以使用简化版,像这样-

goodIDs = np.flatnonzero(np.bincount(data[:,1],data[:,3]==1)>=1)
out = data[np.in1d(data[:,1],goodIDs)]

sample 运行-

In [44]: data
Out[44]: 
array([[20,  0,  5,  1],
       [20,  0,  5,  1],
       [20,  0,  5,  0],
       [20,  1,  5,  0],
       [20,  1,  5,  0],
       [20,  2,  5,  1],
       [20,  3,  5,  0],
       [20,  3,  5,  0],
       [20,  3,  5,  1],
       [20,  4,  5,  0],
       [20,  4,  5,  0],
       [20,  4,  5,  0]])

In [45]: out
Out[45]: 
array([[20,  0,  5,  1],
       [20,  0,  5,  1],
       [20,  0,  5,  0],
       [20,  2,  5,  1],
       [20,  3,  5,  0],
       [20,  3,  5,  0],
       [20,  3,  5,  1]])

此外,如果 data[:,3] 总是有 1 和 0,我们可以只使用 data[:,3] 代替 data[ :,3]==1 在上面列出的代码中。


基准测试

让我们针对更大数组的特定情况对矢量化方法进行基准测试 -

In [69]: def logical_or_based(data): #@ Eric's soln
    ...:     b_vals = data[:,1]
    ...:     d_vals = data[:,3]
    ...:     is_ok = np.zeros(np.max(b_vals) + 1, dtype=np.bool_)
    ...:     np.logical_or.at(is_ok, b_vals, d_vals)
    ...:     return is_ok[b_vals]
    ...: 
    ...: def in1d_based(data):
    ...:     goodIDs = np.flatnonzero(np.bincount(data[:,1],data[:,3])!=0)
    ...:     out = np.in1d(data[:,1],goodIDs)
    ...:     return out
    ...: 

In [70]: # Setup input
    ...: data = np.random.randint(0,100,(10000,4))
    ...: data[:,1] = np.sort(np.random.randint(0,100,(10000)))
    ...: data[:,3] = np.random.randint(0,2,(10000))
    ...: 

In [71]: %timeit logical_or_based(data) #@ Eric's soln
1000 loops, best of 3: 1.44 ms per loop

In [72]: %timeit in1d_based(data)
1000 loops, best of 3: 528 µs per loop

关于python通过一大块数据过滤二维数组,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/40132352/

相关文章:

python - 如何用 2 个参数拆分字符串?

c - 如何更改char数组中的字符

javascript - 使用 JavaScript 查找数组中的最大元素

python - Pandas random_state 究竟做了什么?

Python: "import posix"问题

Python:为什么事件调度程序一直在漂移,有没有办法解决这个问题?

c - 尝试创建一个结构数组并从文件加载数据

python - Numpy:高级切片

python - 对 NumPy 数组进行排序

python - h5py 中的组是否保留其成员添加的顺序?