要获得数组X的最低10个值,我会执行以下操作:
lowest10 = np.argsort(X)[:10]
什么是最有效的方法,避免循环,过滤结果,以便我得到其索引不是另一个数组Y的元素的最低10个值?
例如,如果数组Y是:
[2,20,51]
X [2],X [20]和X [51]不应该被考虑计算最低的10。
答案 0 :(得分:2)
经过一些基准测试后,我的建议很简单:
交换似乎或多或少总是比屏蔽更快(即使禁止99%的X.)所以使用
的内容。swap = X[Y]
X[Y] = np.inf
排序很昂贵,因此请使用argpartition
并仅排序必要的内容。像
lowest10 = np.argpartition(Xfiltered, 10)[:10]
lowest10 = lowest10[np.argsort(Xfiltered[lowest10])]
以下是一些基准:
import numpy as np
from timeit import timeit
def swap_out():
global sol
swap = X[Y]
X[Y] = np.inf
sol = np.argpartition(X, K)[:K]
sol = sol[np.argsort(X[sol])]
X[Y] = swap
def app1():
sidx = X.argsort()
return sidx[~np.in1d(sidx, Y)][:K]
def app2():
sidx = np.argpartition(X,range(K+Y.size))
return sidx[~np.in1d(sidx, Y)][:K]
def app3():
sidx = np.argpartition(X,K+Y.size)
return sidx[~np.in1d(sidx, Y)][:K]
K = 10 # number of small elements wanted
N = 10000 # size of X
M = 10 # size of Y
S = 10 # number of repeats in benchmark
X = np.random.random((N,))
Y = np.random.choice(N, (M,))
so = timeit(swap_out, number=S)
print(sol)
print(X[sol])
d1 = timeit(app1, number=S)
print(sol)
print(X[sol])
d2 = timeit(app2, number=S)
print(sol)
print(X[sol])
d3 = timeit(app3, number=S)
print(sol)
print(X[sol])
print('pp', f'{so:8.5f}', ' d1(um)', f'{d1:8.5f}', ' d2', f'{d2:8.5f}', ' d3', f'{d3:8.5f}')
# pp 0.00053 d1(um) 0.00731 d2 0.00313 d3 0.00149
答案 1 :(得分:1)
您可以使用numpy.delete();
处理原始数组的子集lowest10 = np.argsort(np.delete(X, Y))[:10]
由于删除的工作原理是将原始数组切片以保留索引,因此复杂性应该是不变的。
警告:此解决方案使用原始 X 数组的子集(X没有在Y中索引的元素),因此最终结果将是该子集中最低的10个。
答案 2 :(得分:1)
这是一种方法 -
class Box(models.Model):
name = models.CharField(max_length=120, unique=True)
def __str__(self):
return self.name
class Things(models.Model):
box = models.ForeignKey(Box)
name = models.CharField(max_length=120)
thing_number = models.PositiveIntegerField(default=1)
def __str__(self):
return self.name
示例运行 -
sidx = X.argsort()
idx_out = sidx[~np.in1d(sidx, Y)][:10]
或者,为了提高性能,我们可能希望使用# Setup inputs
In [141]: X = np.random.choice(range(60), 60)
In [142]: Y = np.array([2,20,51])
# For testing, let's set the Y positions as 0s and
# we want to see them skipped in o/p
In [143]: X[Y] = 0
# Use proposed approach
In [144]: sidx = X.argsort()
In [145]: X[sidx[~np.in1d(sidx, Y)][:10]]
Out[145]: array([ 0, 2, 4, 5, 5, 9, 9, 10, 12, 14])
# Print the first 13 numbers and skip three 0s and
# that should match up with the output from proposed approach
In [146]: np.sort(X)[:13]
Out[146]: array([ 0, 0, 0, 0, 2, 4, 5, 5, 9, 9, 10, 12, 14])
,就像这样 -
np.argpartition
如果sidx = np.argpartition(X,range(10+Y.size))
idx_out = X[sidx[~np.in1d(sidx, Y)][:10]]
的长度比X
大得多,那么这将非常有用。
如果你不关心10
索引列表中元素的顺序,为了进一步提升,我们可以简单地将标量长度而不是10
数组传递给{{1} }:range
。
我们可以使用np.argpartition
优化np.argpartition(X,10+Y.size)
,以便再采用一种方法(下一步列出)。
在下面列出了本文所讨论的所有方法 -
np.in1d