2012-03-31 542 views
27

如何更改numpy中矩陣對角線的值?在numpy中更改矩陣對角線的值

我檢查了Numpy modify ndarray diagonal,但是函數沒有在numpy v 1.3.0中實現。

可以說我們有一個np.array X,我想對角線的所有值設置爲0。

+1

你使用的是什麼版本的numpy? 'np.diag_indices_from'在v1.4中加入了 – JoshAdel 2012-03-31 19:21:21

+0

是的,你說得對,我現在正在使用python v 1.3.0 – pacodelumberg 2012-03-31 20:57:10

+0

@LangerHansIslands希望你的意思是numpy 1.3,而不是python 1.3(它出現在90年代中期.. 。:p) – Dougal 2012-03-31 20:59:02

回答

2
def replaceDiagonal(matrix, replacementList): 
    for i in range(len(replacementList)): 
     matrix[i][i] = replacementList[i] 

如果大小是一個n×n矩陣ñ。

+3

或'n = len(replacement_list);矩陣[:n,:n] = replacement_list'。這在C中而不是在Python中循環,所以會更快。 – Dougal 2012-03-31 19:37:54

+0

@Dougal:真棒,我不知道。你能把它作爲答案發布嗎? – 2012-03-31 19:51:56

+0

當然,[只是](http://stackoverflow.com/a/9959707/344821)。 – Dougal 2012-03-31 21:10:09

12

如果您使用的是版本numpy的,其不具有fill_diagonal(在right way對角線設置爲常數),或者diag_indices_from,你可以用數組切片做到這一點很容易地:

# assuming a 2d square array 
n = mat.shape[0] 
mat[range(n), range(n)] = 0 

這比在Python外在的循環快得多,因爲循環發生在C和潛在地量化。

這樣做的一個好處是,您還可以用元素列表填充對角線,而不是一個常量值(如diagflat,但用於修改現有矩陣而不是創建新矩陣)。例如,這將設置對角矩陣的對0,1,2,...:

# again assuming 2d square array 
n = mat.shape[0] 
mat[range(n), range(n)] = range(n) 

如果需要支持更多的數組的形狀,這是更復雜(這就是爲什麼fill_diagonal是好的。 ..):

m[list(zip(*map(range, m.shape)))] = 0 

(該list通話只需要在Python 3,凡zip返回迭代器)

+0

爲了讓將來的讀者清楚,mat [:n,:n] = 0'將整個數組/矩陣設置爲0,而不僅僅是對角元素。 '拉鍊'版本確實做了診斷。 – gorlum0 2013-01-20 11:58:29

+0

@ gorlum0哎呀 - 謝謝你指出。我剛編輯修復它('zip'實際上並不是必需的)''。 – Dougal 2013-01-20 15:28:20

+0

酷,甚至裸'範圍'。這種隱含的東西很難知道。 – gorlum0 2013-01-21 06:07:15

9

下面是做到這一點的另一個好方法。如果你想在陣列的主對角線使用的一維視圖:

A.ravel()[:A.shape[1]**2:A.shape[1]+1] 

對於第i個superdiagonal使用:

A.ravel()[i:max(0,A.shape[1]-i)*A.shape[1]:A.shape[1]+1] 

對於第i次對角使用:

A.ravel()[A.shape[1]*i:A.shape[1]*(i+A.shape[1]):A.shape[1]+1] 

或者一般情況下,對於主對角線爲0的第i個對角線,子對角線爲負值,超對角線爲正,使用:

A.ravel()[max(i,-A.shape[1]*i):max(0,(A.shape[1]-i))*A.shape[1]:A.shape[1]+1] 

這些觀點,而不是拷貝,那麼他們將運行用於提取對角線快,但新的數組對象所做的任何更改將應用​​到原始數組。 在我的機器上,當將主對角線設置爲常量時,它們的運行速度比fill_diagonal函數快,但情況並非總是如此。它們也可以用來爲一個對角線而不是一個常量賦值一個數組。

注意:對於小陣列,使用NumPy數組的flat屬性可能會更快。 如果速度是一個主要問題,它可能是值得的A.shape[1]本地變量。 此外,如果數組不連續,ravel()將返回一個副本,因此,爲了將值分配給跨步切片,需要創建切片用於生成跨步切片的原始數組(如果它是連續的)或使用flat屬性。

此外,最初計劃在NumPy 1.10及更高版本中,數組的「對角線」方法將返回視圖而不是副本。 雖然這個改變還沒有做出,但希望在某個時候這個伎倆來獲得一個觀點將不再是必要的。 見http://docs.scipy.org/doc/numpy-dev/reference/generated/numpy.diagonal.html

+0

尼斯和哈克,我喜歡它!唯一需要注意的是我認爲你會得到['np.fill_diagonal'文檔]中描述的'wrap = True'行爲(http://docs.scipy.org/doc/numpy/reference/generated/numpy.fill_diagonal.html )。你也許可以解決,爲你的切片添加足夠的停止值。 – Jaime 2013-07-23 04:41:21

+0

謝謝,很好。我只是編輯它來解決這個問題和其他一些事情。 – IanH 2013-07-23 05:28:56

1
>>> a = numpy.random.rand(2,2) 
>>> a 
array([[ 0.41668355, 0.07982691], 
     [ 0.60790982, 0.0314224 ]]) 
>>> a - numpy.diag(numpy.diag(a)) 
array([[ 0.  , 0.07982691], 
     [ 0.60790982, 0.  ]]) 
4

最小。碼。

X[np.diag_indices_from(X)] = 0. 

screenshot

1

你可以做到以下幾點。

假設您的矩陣是4 * 4矩陣。

indices_diagonal = np.diag_indices(4) 

yourarray[indices_diagonal] = Val