我有一个数组n x m,每列的最大值。除了检查每个元素之外,更换大于最大值的值的最佳方法是什么?
例如:
def check_limits(bad_array, maxs):
good_array = np.copy(bad_array)
for i_line in xrange(bad_array.shape[0]):
for i_column in xrange(bad_array.shape[1]):
if good_array[i_line][i_column] >= maxs[i_column]:
good_array[i_line][i_column] = maxs[i_column] - 1
return good_array
无论如何要更快更简洁地完成这项工作?
答案 0 :(得分:8)
使用putmask:
import numpy as np
a = np.array([[ 0, 1, 2, 3],
[ 4, 5, 6, 7],
[ 8, 9, 10, 11]])
m = np.array([7,6,5,4])
# This is what you need:
np.putmask(a, a >= m, m - 1)
# a is now:
np.array([[0, 1, 2, 3],
[4, 5, 4, 3],
[6, 5, 4, 3]])
答案 1 :(得分:0)
如果我们不对bad_array
的结构做任何假设,那么你的代码就是对手论证的最佳选择。如果我们知道每列按升序排序,那么一旦我们达到高于最大值的值,那么我们就知道该列中的每个后续元素也高于限制,但如果我们没有这样的假设,我们只需要检查每一个。
如果您决定先对每一列进行排序,则需要(n列* nlogn)时间,该时间已经大于检查每个元素所需的n * n时间。
您还可以通过一次检查和复制一个元素来创建good_array
,而不是复制bad_array
中的所有元素并在以后检查它们。这应该大致减少0.5倍的时间
答案 2 :(得分:0)
如果列数不大,则一个优化是:
def check_limits(bad_array, maxs):
good_array = np.copy(bad_array)
for i_column in xrange(bad_array.shape[1]):
to_replace = (good_array[:,i_column] >= maxs[i_column])
good_array[to_replace, i_column] = maxs[i_column] - 1
return good_array
答案 3 :(得分:0)
另一种方法是使用clip函数:
使用eumiro的例子:
bad_array = np.array([[ 0, 1, 2, 3],
[ 4, 5, 6, 7],
[ 8, 9, 10, 11]])
maxs = np.array([7,6,5,4])
good_array = bad_array.clip(max=maxs-1)
OR
bad_array.clip(max=maxs-1, out=good_array)
您还可以通过添加参数min =
来指定下限