我想创建一个二进制数组,显示numpy数组中的所有匹配行。在这种情况下,如果新矩阵的下一列j
,如果原始矩阵中的行1
与来自行i
的行j
相同,则第i个索引将对应[ [a b c]
[d e f]
[a b c]
[d e f]]
原始矩阵。
例如,如果矩阵看起来像:
[[1 0 1 0]
[0 1 0 1]
[1 0 1 0]
[0 1 0 1]]
我想输出的是
same_mat=np.empty((agents,agents))
for i in range(matrix.shape[0]):
same_mat[:,i]=np.all(matrix[i,:]==matrix,axis=1)
现在,我通过这样的循环来做这件事:
SELECT IF(Condition < Y, 'Less Than Y', 'GTE Y'), AVG(stars)
FROM long expression
GROUP BY 1
然而,这很慢,因为它必须单独遍历原始矩阵中的每一行,以生成新矩阵中的每一列。有没有任何矢量化方法可以更快地完成这项工作?
由于
答案 0 :(得分:2)
方法#1:我们可以简单地将数组扩展到两个3D版本并进行比较,从而让broadcasting
发挥其魔力 -
(arr[:,None] == arr).all(2).astype(int)
示例运行 -
In [19]: a,b,c,d,e,f = 4,7,3,1,8,2
...: arr = np.array([
...: [a, b, c],
...: [d ,e, f],
...: [a ,b, c],
...: [d ,e, f]])
...:
In [20]: arr
Out[20]:
array([[4, 7, 3],
[1, 8, 2],
[4, 7, 3],
[1, 8, 2]])
In [21]: (arr[:,None] == arr).all(2).astype(int)
Out[21]:
array([[1, 0, 1, 0],
[0, 1, 0, 1],
[1, 0, 1, 0],
[0, 1, 0, 1]])
方法#2:使用views
的内存效率方法,因为我们将每行减少到一个值,然后执行broadcasted-comparison
- < / p>
# https://stackoverflow.com/a/44999009/ @Divakar
def view1D(a): # a is array
a = np.ascontiguousarray(a)
void_dt = np.dtype((np.void, a.dtype.itemsize * a.shape[1]))
return a.view(void_dt).ravel()
arr1D = view1D(arr)
out = (arr1D[:,None] == arr1D).astype(int)
方法#3:对于内置插件的喜爱,这是另一个在理论上与前一个相似的内容,但使用np.unique
及其新的axis
功能 -
ids = np.unique(arr, axis=0, return_inverse=1)[1]
out = (ids[:,None] == ids).astype(int)
方法#4:根据其他行中的唯一性来标记每一行的另一种方法是将每一行视为2D
网格上的线性索引等价物,给我们获得ids
-
ids = arr.dot((arr.max()-arr.min()+1)**np.arange(arr.shape[1]))
out = (ids[:,None] == ids).astype(int)
如果我们保证有正数,请跳过arr.min()
。
我们需要在这里小心,因为数字的巨大变化或列数很多会导致溢出。因此,在使用这种方法时请记住这些。
额外的东西
要挤出最高性能,请使用uint8
作为输出dtype,这似乎很好,因为我们只需要在输出中包含0s
和1s
,如下面的时间所示 -
In [41]: bool_arr = np.random.rand(100,100)>0.5
In [42]: %timeit bool_arr.astype(int)
...: %timeit bool_arr.astype(np.uint8)
...:
100000 loops, best of 3: 4.15 µs per loop
1000000 loops, best of 3: 897 ns per loop
In [43]: bool_arr = np.random.rand(5000,5000)>0.5
In [44]: %timeit bool_arr.astype(int)
...: %timeit bool_arr.astype(np.uint8)
...:
10 loops, best of 3: 21 ms per loop
100 loops, best of 3: 3.16 ms per loop