2012-03-31 2 views
27

행렬의 대각선 값을 numpy로 어떻게 변경합니까?numpy에서 행렬의 대각선 값을 변경하십시오.

나는 Numpy modify ndarray diagonal을 점검했지만, numpy v 1.3.0에는이 기능이 구현되어 있지 않습니다.

우리가 np.array의 X를 가지고 있고이 0 크기는 n × n의 매트릭스 형으로 n은

+1

어떤 numpy 버전을 사용하고 있습니까? 'np.diag_indices_from'이 v1.4에 추가되었습니다. – JoshAdel

+0

예, 맞습니다. 현재 python v 1.3.0을 사용하고 있습니다. – pacodelumberg

+0

@LangerHansIslands 바라건대 numpy 1.3이 아니라 python 1.3이 필요합니다. (90 년대 중반에 나왔습니다.) . : p) – Dougal

답변

36

numpy.fill_diagonal을 사용해 보셨습니까? 다음 answerdiscussion을 참조하십시오. 또는 (현재 깨진 있지만) 문서에서 다음

http://docs.scipy.org/doc/numpy/reference/generated/numpy.fill_diagonal.html

+0

감사합니다 @JoshAdel – Mellkor

+0

+1 이것은 numpy에서 이것을하는 적절한 방법입니다. 내장 함수는 두 개의 for 루프를 사용하여 한 번에 한 요소 씩 배열을 반복하는 것이 항상 바람직합니다. – JoshAdel

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

에 대각선의 모든 값을 설정하려는 말할 수 있습니다.

+3

또는'n = len (replacement_list); 행렬 [: n, : n] = 대체 목록. 이렇게하면 파이썬 대신 C로 루프가 수행되므로 훨씬 빨라집니다. – Dougal

+0

@Dougal : 신난다. 나는 그것을 모르고 있었다. 답변으로 게시 할 수 있습니까? –

+0

물론, [그냥 않았다] (http://stackoverflow.com/a/9959707/344821). – Dougal

12

당신이 diag_indices_from 또는 (일정에 대각선을 설정 right way) fill_diagonal이없는 NumPy와의 버전을 사용하는 경우, 당신은 배열 슬라이스로 아주 ​​쉽게이 작업을 수행 할 수 있습니다

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

루핑은 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 호출 zip이 반복자를 반환 파이썬 3 만 필요)

+0

미래의 독자를 위해 'mat [: n, : n] = 0'은 대각 요소가 아니라 전체 배열/행렬 _을 0으로 설정합니다. 'zip' 버전은 정말로 diag를합니다. – gorlum0

+0

@ gorlum0 으음 - 그 점을 지적 해 주셔서 감사합니다. 나는 그것을 고치기 위해 편집했다. ('zip'은 실제로 거기에서 필요하지 않습니다.)' – Dougal

+0

차가운 심지어 범위 '범위'. 이 암묵적인 내용은 알기가 어렵습니다. – gorlum0

9

가 여기에이 작업을 수행하는 또 다른 좋은 방법입니다.. i 번째 superdiagonal 사용하기 위해

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

: : i 번째 subdiagonal 사용하기 위해

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

:

A.ravel()[A.shape[1]*i:A.shape[1]*(i+A.shape[1]):A.shape[1]+1] 
당신은 배열의 주요 대각선 사용의 1 차원보기를 원하는 경우

또는 일반적으로 주 대각선이 0 인 i 번째 대각선에 대해 부 대각선은 음수이고 수퍼 대각선은 양수입니다.

이러한보기는 아닌 사본이기 때문에 더 빨리 대각선 추출 실행되지만 새로운 어레이 오브젝트에 대한 변경은 원래의 배열에 적용된다. 내 컴퓨터에서이 함수는 주 대각선을 상수로 설정할 때 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

+0

고마워요, 잘 잡으세요. 방금 수정 한 내용과 다른 몇 가지 사항을 수정했습니다. – IanH

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 
관련 문제