2011-03-31 74 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) 

還可以指定的下限,通過將參數分=