让我们假设我们有一个数组A
如果shape (100,)
和B
的shape (10,)
。两者都包含[0,1]中的值
如何使A
中的元素计数大于B
中的每个值?我期望一个(10,)
的形状,其中第一个元素是“多少in A
大于B[0]
”,第二个是“多少in A
大于B[1]
”,等等
不使用循环
我尝试了以下方法,但无效:
import numpy as np
import numpy.random as rdm
A = rdm.rand(100)
B = np.linspace(0,1,10)
def occ(z: float) ->float:
return np.count_nonzero(A > z)
occ(B)
Python不会将我的函数用作B
上的标量函数,这就是为什么我得到:
operands could not be broadcast together with shapes (10,) (100,)
我也尝试过np.greater
,但我也遇到了同样的问题
我想你可以用np.histogram做这项工作
给出输出
B[9]
将始终为空,因为没有值>;1.然后向后计算总和
输出
解释
需要了解broadcasting并为此进行重塑。通过将B重塑为shape(len(B),1),它可以与A一起广播以生成包含所有比较的shape(len(B),len(A))的数组。然后在轴1上求和(沿A)
换句话说,
A < B
不起作用,因为A
有100个条目,而B有10个条目。如果您阅读broadcasting rules,您将看到numpy将从最后一个维度开始,如果它们的大小相同,那么它可以一对一进行比较。如果这两个维度中的一个是1
,则此维度将被拉伸或“复制”以匹配另一个。如果它们不相等,并且没有一个等于1
,则失败举一个简短的例子:
(A>B.reshape((-1,1)))
的转置(为了可读性)而且{}是
缓慢但简单
如果您不理解错误消息,则错误消息很神秘,但它会告诉您该怎么做。数组维度从右边缘开始排列在一起broadcast。如果您将操作分为两部分,这将特别有用:
创建一个
(100, 10)
掩码,显示A
的哪些元素大于B
的哪些元素:沿与
A
相对应的轴对上一次操作的结果求和:或
这可以写成一行:
或
您可以切换尺寸并将
B
放置在第一个轴上,以获得相同的结果:快速优雅
采用完全不同(但可能更有效)的方法,您可以使用^{} :
默认情况下,
searchsorted
返回左索引,B
的每个元素将被插入A
at。这会立即告诉您A
中有多少元素大于这个值基准
此处,ALGO标记如下:
B0
:(A[:, None] > B).sum(0)
B1
:(A > B[:, None]).sum(1)
HH
:np.cumsum(np.histogram(A, bins=B)[0][::-1])[::-1]
SS
:A.sort(); A.size - np.searchsorted(A, B)
内存布局很重要
B1
总是比B0
快。之所以会出现这种情况,是因为对连续(缓存)元素(沿C顺序的最后一个轴)求和总是比跳过行以获取下一个元素要快。广播对于B
的小值表现良好。请记住B0
和B1
的时间和空间复杂性都是O(A.size * B.size)
。这两种组织编程解决方案的复杂性应该是O(A.size * log(A.size))
,但是SS
的实现效率要比HH
高很多,因为它可以承担更多的数据方面的事情相关问题 更多 >
编程相关推荐