2012-03-31 38 views
27

làm cách nào tôi có thể thay đổi giá trị của đường chéo của ma trận theo dạng khối u?thay đổi các giá trị của đường chéo của ma trận ở dạng khối u

Tôi đã kiểm tra Numpy modify ndarray diagonal, nhưng chức năng không được triển khai trong numpy v 1.3.0.

cho phép nói rằng chúng tôi có một np.array X và tôi muốn đặt tất cả các giá trị của các đường chéo để 0.

+1

Bạn đang sử dụng phiên bản nào? 'np.diag_indices_from' được thêm vào trong v1.4 – JoshAdel

+0

vâng, bạn nói đúng, tôi hiện đang sử dụng python v 1.3.0 – pacodelumberg

+0

@LangerHansIslands Hy vọng rằng bạn có nghĩa là gumpy 1.3, không phải python 1.3 (xuất hiện vào giữa những năm chín mươi). .: p) – Dougal

Trả lời

36

Bạn đã thử numpy.fill_diagonal? Xem answer sau đây và discussion này. Hoặc sau từ tài liệu (mặc dù hiện đang bị hỏng):

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

+0

Cảm ơn bạn @JoshAdel – Mellkor

+0

+1 Đây là cách thích hợp để thực hiện việc này một cách gọn gàng. Việc xây dựng trong luôn luôn là thích hợp hơn để lặp mảng một phần tử tại một thời điểm bằng cách sử dụng hai cho các vòng lặp. – JoshAdel

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

đâu kích thước là n trong một ma trận n x n.

+3

Hoặc 'n = len (replace_list); ma trận [: n,: n] = replace_list'. Điều này làm vòng lặp trong C thay vì bằng Python và do đó sẽ nhanh hơn nhiều. – Dougal

+0

@Dougal: Tuyệt vời, tôi không biết điều đó. Bạn có thể đăng nó như là một câu trả lời? –

+0

Chắc chắn, [vừa mới] (http://stackoverflow.com/a/9959707/344821). – Dougal

12

Nếu bạn đang sử dụng một phiên bản của NumPy mà không có fill_diagonal (các right way để thiết lập các đường chéo để một hằng số) hoặc diag_indices_from, bạn có thể làm điều này khá dễ dàng với mảng cắt:

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

Điều này nhanh hơn nhiều so với vòng lặp rõ ràng trong Python, vì vòng lặp xảy ra trong C và có khả năng được vector hóa.

Một điều thú vị về điều này là bạn cũng có thể điền vào một đường chéo với danh sách các phần tử, thay vì giá trị không đổi (như diagflat, nhưng để sửa đổi ma trận hiện có thay vì tạo ma trận mới). Ví dụ, điều này sẽ thiết lập các đường chéo của ma trận của bạn để 0, 1, 2, ...:

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

Nếu bạn cần hỗ trợ nhiều hình dạng mảng, đây là phức tạp hơn (đó là lý do fill_diagonal là tốt đẹp. ..):

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

(cuộc gọi list chỉ cần thiết trong Python 3, nơi zip trả về một iterator)

+0

Để làm rõ cho người đọc trong tương lai, 'mat [: n,: n] = 0' đặt _ toàn bộ mảng/ma trận_ thành 0, không chỉ các phần tử đường chéo. Phiên bản 'zip' thực sự là diag. – gorlum0

+0

@ gorlum0 Rất tiếc - cảm ơn bạn đã chỉ ra điều đó. Tôi chỉ chỉnh sửa để sửa chữa nó ('zip' là không thực sự cần thiết ở đó)'. – Dougal

+0

Mát mẻ, thậm chí là trần 'dải ô'. Những thứ ngầm định này khó có thể biết được. – gorlum0

9

đây là một cách tốt để làm điều này.. Nếu bạn muốn có một cái nhìn một chiều sử dụng đường chéo chính của mảng:

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

Đối với i'th sử dụng superdiagonal:

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

Đối với i'th sử dụng subdiagonal:

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

Hoặc nói chung, đối với đường chéo thứ i nơi đường chéo chính là 0, các đường phụ là số âm và đường siêu hình là số dương, sử dụng:

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

Đây là những quan điểm và không sao chép, vì vậy họ sẽ chạy nhanh hơn để trích xuất một đường chéo, nhưng bất cứ thay đổi nào đối tượng mảng mới sẽ áp dụng cho các mảng ban đầu. Trên máy của tôi, chúng chạy nhanh hơn hàm fill_diagonal khi thiết lập đường chéo chính thành hằng số, nhưng điều đó có thể không phải lúc nào cũng đúng. Chúng cũng có thể được sử dụng để gán một mảng các giá trị cho một đường chéo thay vì chỉ là một hằng số.

Lưu ý: đối với mảng nhỏ, có thể sử dụng thuộc tính flat của mảng NumPy nhanh hơn. Nếu tốc độ là một vấn đề lớn, nó có thể là giá trị để biến A.shape[1] biến cục bộ. Ngoài ra, nếu mảng không tiếp giáp, ravel() sẽ trả về một bản sao, do đó, để gán các giá trị cho một lát cắt, cần phải tạo một cách sáng tạo mảng ban đầu được sử dụng để tạo slice được cắt (nếu nó tiếp giáp) hoặc sử dụng thuộc tính flat.

Ngoài ra, ban đầu nó được lên kế hoạch rằng trong NumPy 1.10 và sau đó phương pháp 'chéo' của mảng sẽ trả về dạng xem thay vì sao chép. Thay đổi đó vẫn chưa được thực hiện mặc dù, nhưng hy vọng tại một số điểm lừa này để có được một cái nhìn sẽ không còn cần thiết. Xem http://docs.scipy.org/doc/numpy-dev/reference/generated/numpy.diagonal.html

+0

Đẹp và bị hack, tôi thích nó! Chỉ báo trước là tôi nghĩ bạn sẽ nhận được hành vi 'wrap = True' được mô tả trong tài liệu [' np.fill_diagonal'] (http://docs.scipy.org/doc/numpy/reference/generated/numpy.fill_diagonal.html). Bạn có thể có thể giải quyết rằng thêm một giá trị dừng đầy đủ cho lát của bạn. – Jaime

+0

Cảm ơn bạn, bắt tốt. Tôi chỉ chỉnh sửa nó để sửa lỗi đó và một số thứ khác. – 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

Tối thiểu. Mã.

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

screenshot

1

Bạn có thể làm như sau.

Giả sử ma trận của bạn là ma trận 4 * 4.

indices_diagonal = np.diag_indices(4) 

yourarray[indices_diagonal] = Val 
Các vấn đề liên quan