...而且该引用来自一个单独的矩阵。
这个问题是前面回答的问题的扩展,其中引用元素直接来自与之比较的同一列。一些聪明的排序和引用排序的索引似乎解决了那个。
原始问题和新问题都提出了广播。我在 n ~ 3000
附近内存不足,需要另一个数量级更大。
为了让提议的解决方案在 [SPACE]
- 和 [TIME]
-domains <登记/>
我们假设 n = 50000; m = 20; k = 50; a = np.random.rand( n, m ); ...
我现在对更通用的形式感兴趣,其中参考值来自另一个参考值矩阵。
原始问题:
Vectorized pythonic way to get count of elements greater than current element
新问题:我们可以编写一个矢量化形式来执行以下角色吗?
函数接收2个2-d数组作为输入。
A = n x m
B = k x m
并返回
C = k x m.
C[i,j]
是 A[:,j]
(仅j
- 列)中大于<的观察比例强> B[i,j]
这是我用于循环实现的令人尴尬的慢速双倍。
import numpy as np
n = 100
m = 20
k = 50
a = np.random.rand(n,m)
b = np.random.rand(k,m)
c = np.zeros((k,m))
for j in range(0,m): #cols
for i in range(0,k): # rows
r = b[i,j]
c[i,j] = ( ( a[:,j] > r).sum() ) / (n)
答案 0 :(得分:3)
我们可以再次使用this solution
中讨论的argsort
技巧,但有点扭曲。我们将第二个数组连接到第一个数组,然后执行argsort-ing
。我们需要对连接数组和第二个数组使用argsort
并得到我们想要的输出。实现看起来像这样 -
ab = np.vstack((a,b))
len_a, len_b = len(a), len(b)
b_argoffset = b.argsort(0).argsort(0)
total_args = ab.argsort(0).argsort(0)[-len_b:]
out = len_a - total_args + b_argoffset
<强>解释强>
argsort
来获取第二个数组w.r.t到整个连接数组的相对位置,再使用一个argsort
来追溯原始顺序的那些索引。argsort-ing
,以便补偿连接。b
中的每个元素进行比较:a[:,j] > b[i,j]
。现在,这些索引顺序是基于0的,即更接近0
的索引表示a[:,j]
中的元素数量大于当前元素b[i,j]
,因此计数更多,反之亦然。因此,我们需要从最终输出的a[:,j]
长度中减去这些索引。我们会使用array-assignment
进一步优化它,再次受到来自同一解决方案的Approach #2
的启发。那么,那些arg输出:b_argoffset
和total_args
可以替代地计算,如此 -
def unqargsort(a):
n,m = a.shape
idx = a.argsort(0)
out = np.zeros((n,m),dtype=int)
out[idx, np.arange(m)] = np.arange(n)[:,None]
return out
b_argoffset = unqargsort(b)
total_args = unqargsort(ab)[-len_b:]
我们还可以利用searchsorted
来实现完全不同的方法 -
k,m = b.shape
sidx = a.argsort(0)
out = np.empty((k,m), dtype=int)
for i in range(m): #cols
out[:,i] = np.searchsorted(a[:,i], b[:,i],sorter=sidx[:,i])
out = len(a) - out
<强>解释强>
a
的每列的排序顺序索引。b
放入带有a
的已排序searcshorted
中。这使我们与Approach#1
中的步骤#3,4的输出相同。请注意,这些方法可以为我们提供支持。因此,对于最终输出,将由此获得的输出除以n
。
答案 1 :(得分:2)
我认为你可以使用广播:
c = (a[:,None,:] > b).mean(axis=0)
演示:
In [207]: n = 5
In [208]: m = 3
In [209]: a = np.random.randint(10, size=(n,m))
In [210]: b = np.random.randint(10, size=(n,m))
In [211]: c = np.zeros((n,m))
In [212]: a
Out[212]:
array([[2, 2, 8],
[5, 0, 8],
[2, 5, 7],
[4, 4, 4],
[2, 6, 7]])
In [213]: b
Out[213]:
array([[3, 6, 8],
[2, 7, 5],
[8, 9, 2],
[9, 8, 7],
[2, 7, 2]])
In [214]: for j in range(0,m): #cols
...: for i in range(0,n): # rows
...: r = b[i,j]
...: c[i,j] = ( ( a[:,j] > r).sum() ) / (n)
...:
...:
In [215]: c
Out[215]:
array([[0.4, 0. , 0. ],
[0.4, 0. , 0.8],
[0. , 0. , 1. ],
[0. , 0. , 0.4],
[0.4, 0. , 1. ]])
In [216]: (a[:,None,:] > b).mean(axis=0)
Out[216]:
array([[0.4, 0. , 0. ],
[0.4, 0. , 0.8],
[0. , 0. , 1. ],
[0. , 0. , 0.4],
[0.4, 0. , 1. ]])
检查:
In [217]: ((a[:,None,:] > b).mean(axis=0) == c).all()
Out[217]: True