假设我有一个像这样的数组:
import numpy as np
base_array = np.array([-13, -9, -11, -3, -3, -4, 2, 2,
2, 5, 7, 7, 8, 7, 12, 11])
假设我想知道:“ base_array
中有多少个元素大于4?”这可以通过利用广播来简单地完成:
np.sum(4 < base_array)
答案为7
。现在,假设我不想对单个值进行比较,而是想对一个数组进行比较。换句话说,对于c
中的每个值comparison_array
,找出base_array
的多少个元素大于c
。如果我以这种天真的方式进行操作,它显然会失败,因为它不知道如何正确广播它:
comparison_array = np.arange(-13, 13)
comparison_result = np.sum(comparison_array < base_array)
输出:
Traceback (most recent call last):
File "<pyshell#87>", line 1, in <module>
np.sum(comparison_array < base_array)
ValueError: operands could not be broadcast together with shapes (26,) (16,)
如果我能以某种方式让comparison_array
的每个元素广播到base_array
的形状,那就可以解决这个问题。但是我不知道如何进行这种“逐元素广播”。
现在,我确实知道我如何使用列表理解来实现这两种情况:
first = sum([4 < i for i in base_array])
second = [sum([c < i for i in base_array])
for c in comparison_array]
print(first)
print(second)
输出:
7
[15, 15, 14, 14, 13, 13, 13, 13, 13, 12, 10, 10, 10, 10, 10, 7, 7, 7, 6, 6, 3, 2, 2, 2, 1, 0]
但是,众所周知,这将比在大型数组上正确矢量化的numpy
实现要慢几个数量级。因此,我应该如何在numpy
中做到这一点,以便快速?理想情况下,此解决方案应该扩展到广播工作的任何类型的操作,而不仅仅是在此示例中大于或小于该操作。
答案 0 :(得分:3)
您可以简单地向比较数组添加一个维度,以便在新维度的所有值之间“拉伸”比较。
>>> np.sum(comparison_array[:, None] < base_array)
228
这是broadcasting的基本原理,适用于各种操作。
如果需要沿某个轴求和,只需在比较后指定要沿其求和的轴即可。
>>> np.sum(comparison_array[:, None] < base_array, axis=1)
array([15, 15, 14, 14, 13, 13, 13, 13, 13, 12, 10, 10, 10, 10, 10, 7, 7,
7, 6, 6, 3, 2, 2, 2, 1, 0])
答案 1 :(得分:1)
您将需要转置其中一个阵列以进行广播以使其正常工作。当您一起广播两个阵列时,尺寸会对齐,并且任何单位尺寸都会有效地扩展到它们匹配的非单位尺寸。因此,大小为(16, 1)
(原始数组)和(1, 26)
(比较数组)的两个数组将广播到(16, 26)
。
别忘了对尺寸16的尺寸求和。
(base_array[:, None] > comparison_array).sum(axis=1)
切片中的 None
等效于np.newaxis
:这是在指定索引处插入新单位尺寸的多种方法之一。您无需执行comparison_array[None, :]
的原因是,广播会排列最大的尺寸,并自动用最小的尺寸填充。
答案 2 :(得分:1)
这里是np.searchsorted
的一个,重点是内存效率和性能-
@(Html.Kendo().Grid(Model.MyModel)
.
.
.
.DataSource(ds => ds
.Ajax()
.Read(r => r.Action("GetReport", "MyController", Model))
时间-
def get_comparative_sum(base_array, comparison_array):
n = len(base_array)
base_array_sorted = np.sort(base_array)
idx = np.searchsorted(base_array_sorted, comparison_array, 'right')
idx[idx==n] = n-1
return n - idx - (base_array_sorted[idx] == comparison_array)