获得许多掩码的每个掩码 np.array 最大值的最快方法?
fastest way to get max value of each masked np.array for many masks?
我有两个相同形状的 numpy 数组。一个包含我感兴趣的信息,另一个包含一堆可以用作掩码值的整数。
本质上,我想遍历每个唯一整数以获得数组的每个掩码,然后使用此掩码过滤主数组并找到过滤后数组的最大值。
为简单起见,假设数组是:
arr1 = np.random.rand(10000,10000)
arr2 = np.random.randint(low=0, high=1000, size=(10000,10000))
现在我正在这样做:
maxes = {}
ids = np.unique(arr2)
for id in ids:
max_val = arr1[np.equal(arr2, id)].max()
maxes[id] = max_val
我的数组大了很多,而且速度非常慢,我正在努力寻找一种更快的方法...也许有某种我不知道的创造性方法,非常感谢任何帮助。
编辑
假设 arr2 的大部分实际上是 0 而我不关心 0 id,是否可以通过从搜索中删除整个块来加快速度?
即
arr2[:, 0:4000] = 0
并且只是 return ID > 0 的最大值??
非常感谢..
基于 bin 的通用缩减策略
下面列出了一些解决我们需要执行基于 bin 的缩减操作的场景的方法。所以,基本上我们有两个数组,我们需要使用一个作为 bins,另一个作为值,并减少第二个。
方法 #1: 一种策略是根据 arr2
对 arr1
进行排序。一旦我们以相同的顺序对它们进行排序,我们就会找到组的开始和停止索引,然后使用适当的 ufunc.reduceat
,我们进行基于切片的归约操作。仅此而已!
这是实现 -
def binmax(bins, values, reduceat_func):
''' Get binned statistic from two 1D arrays '''
sidx = bins.argsort()
bins_sorted = bins[sidx]
grpidx = np.flatnonzero(np.r_[True,bins_sorted[:-1]!=bins_sorted[1:]])
max_per_group = reduceat_func(values[sidx],grpidx)
out = dict(zip(bins_sorted[grpidx], max_per_group))
return out
out = binmax(arr2.ravel(), arr1.ravel(), reduceat_func=np.maximum.reduceat)
它适用于具有相应 ufunc.reduceat
方法的 ufunc。
方法 #2: 我们还可以利用 scipy.stats.binned_statistic
,它基本上是一个通用实用程序,可以根据分箱数组值执行一些常见的归约操作 -
from scipy.stats import binned_statistic
def binmax_v2(bins, values, statistic):
''' Get binned statistic from two 1D arrays '''
num_labels = bins.max()+1
R = np.arange(num_labels+1)
Mx = binned_statistic(bins, values, statistic=statistic, bins=R)[0]
idx = np.flatnonzero(~np.isnan(Mx))
out = dict(zip(idx, Mx[idx].astype(int)))
return out
out = binmax_v2(arr2.ravel(), arr1.ravel(), statistic='max')
我有两个相同形状的 numpy 数组。一个包含我感兴趣的信息,另一个包含一堆可以用作掩码值的整数。
本质上,我想遍历每个唯一整数以获得数组的每个掩码,然后使用此掩码过滤主数组并找到过滤后数组的最大值。
为简单起见,假设数组是:
arr1 = np.random.rand(10000,10000)
arr2 = np.random.randint(low=0, high=1000, size=(10000,10000))
现在我正在这样做:
maxes = {}
ids = np.unique(arr2)
for id in ids:
max_val = arr1[np.equal(arr2, id)].max()
maxes[id] = max_val
我的数组大了很多,而且速度非常慢,我正在努力寻找一种更快的方法...也许有某种我不知道的创造性方法,非常感谢任何帮助。
编辑
假设 arr2 的大部分实际上是 0 而我不关心 0 id,是否可以通过从搜索中删除整个块来加快速度?
即
arr2[:, 0:4000] = 0
并且只是 return ID > 0 的最大值??
非常感谢..
基于 bin 的通用缩减策略
下面列出了一些解决我们需要执行基于 bin 的缩减操作的场景的方法。所以,基本上我们有两个数组,我们需要使用一个作为 bins,另一个作为值,并减少第二个。
方法 #1: 一种策略是根据 arr2
对 arr1
进行排序。一旦我们以相同的顺序对它们进行排序,我们就会找到组的开始和停止索引,然后使用适当的 ufunc.reduceat
,我们进行基于切片的归约操作。仅此而已!
这是实现 -
def binmax(bins, values, reduceat_func):
''' Get binned statistic from two 1D arrays '''
sidx = bins.argsort()
bins_sorted = bins[sidx]
grpidx = np.flatnonzero(np.r_[True,bins_sorted[:-1]!=bins_sorted[1:]])
max_per_group = reduceat_func(values[sidx],grpidx)
out = dict(zip(bins_sorted[grpidx], max_per_group))
return out
out = binmax(arr2.ravel(), arr1.ravel(), reduceat_func=np.maximum.reduceat)
它适用于具有相应 ufunc.reduceat
方法的 ufunc。
方法 #2: 我们还可以利用 scipy.stats.binned_statistic
,它基本上是一个通用实用程序,可以根据分箱数组值执行一些常见的归约操作 -
from scipy.stats import binned_statistic
def binmax_v2(bins, values, statistic):
''' Get binned statistic from two 1D arrays '''
num_labels = bins.max()+1
R = np.arange(num_labels+1)
Mx = binned_statistic(bins, values, statistic=statistic, bins=R)[0]
idx = np.flatnonzero(~np.isnan(Mx))
out = dict(zip(idx, Mx[idx].astype(int)))
return out
out = binmax_v2(arr2.ravel(), arr1.ravel(), statistic='max')