2011-03-31 83 views
4

我有一个数组n×m,每列的最大值。除了检查每个元素之外,替代大于最大值的值的最佳方法是什么?在numpy数组中替换大于极限的值

例如:

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 

无论如何要做到这一点更快,更简洁的方式?

回答

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]]) 
+2

此功能从NumPy 1.7开始不推荐使用。使用函数[np.copyto(a,values,where = mask)](http://docs.scipy.org/doc/numpy/reference/generated/numpy.copyto.html)来实现此功能。 – DenisKolodin 2011-11-21 09:00:11

0

如果我们不假设bad_array的结构有任何问题,那么您的代码在对手参数中是最优的。如果我们知道每列按升序排序,那么只要我们达到高于最大值的值,那么我们知道该列中的每个后续元素也高于极限,但如果我们没有这样的假设,我们只需要检查每一个。

如果您决定先对每列进行排序,则需要(n列* nlogn)时间,该时间已经大于检查每个元素所花费的n * n时间。

您也可以通过一次检查并复制一个元素来创建good_array,而不是复制bad_array中的所有元素,并稍后检查它们。这应该.5

+0

如果让numpy的(高度优化的库)来操纵阵列本身,这将是更比对其元素的python迭代更快。 – eumiro 2011-03-31 06:22:23

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 
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) 

还可以指定的下限,通过将参数分=