2015-01-10 46 views
5

Tôi muốn thay đổi các phần tử đường chéo từ ma trận 2d. Đây là cả hai đường chéo chính và không chính.Numpy: Ảnh hưởng đến các yếu tố đường chéo của ma trận trước 1.10

numpy.diagonal() Trong NumPy 1.10, nó sẽ trở lại một cái nhìn đọc/ghi, Viết để trở mảng sẽ làm thay đổi mảng ban đầu của bạn.

numpy.fill_diagonal(), numpy.diag_indices() Chỉ làm việc với các yếu tố chính-chéo

Đây là trường hợp sử dụng của tôi: Tôi muốn tạo một ma trận của các hình thức sau đây, đó là rất tầm thường khi sử dụng ký hiệu đường chéo cho rằng tôi có tất cả các mẫu x, y, z làm mảng.

matrix

+0

còn về 'numpy.diag' thì sao? – talonmies

+1

Tôi nghĩ 'np.diag' gọi' np.diagonal', trước Numpy 1.10, trình bày [khó khăn] (http://docs.scipy.org/doc/numpy/reference/generated/numpy.diagonal.html) khi cố gắng ghi các giá trị vào mảng. –

+0

Có thể xem ['scipy.sparse.diags'] (http://docs.scipy.org/doc/scipy-0.14.0/reference/generated/scipy.sparse.diags.html) và [' scipy .sparse.dia_matrix'] (http://docs.scipy.org/doc/scipy-0.14.0/reference/generated/scipy.sparse.dia_matrix.htm). –

Trả lời

4

Bạn luôn có thể sử dụng cắt để gán giá trị o r mảng đến diagonals.

Chuyển vào danh sách các chỉ mục hàng và danh sách chỉ mục cột cho phép bạn truy cập trực tiếp vào các vị trí (và hiệu quả). Ví dụ:

>>> z = np.zeros((5,5)) 
>>> z[np.arange(5), np.arange(5)] = 1 # diagonal is 1 
>>> z[np.arange(4), np.arange(4) + 1] = 2 # first upper diagonal is 2 
>>> z[np.arange(4) + 1, np.arange(4)] = [11, 12, 13, 14] # first lower diagonal values 

thay đổi mảng các zeros z tới:

array([[ 1., 2., 0., 0., 0.], 
     [ 11., 1., 2., 0., 0.], 
     [ 0., 12., 1., 2., 0.], 
     [ 0., 0., 13., 1., 2.], 
     [ 0., 0., 0., 14., 1.]]) 

Nói chung cho một mảng k x k gọi z, bạn có thể thiết lập các thứ i trên đường chéo với

z[np.arange(k-i), np.arange(k-i) + i] 

và đường chéo thấp hơn i th với

z[np.arange(k-i) + i, np.arange(k-i)] 

Lưu ý: nếu bạn muốn tránh gọi np.arange nhiều lần, bạn chỉ có thể viết ix = np.arange(k) lần và sau đó cắt phạm vi đó khi cần thiết:

np.arange(k-i) == ix[:-i] 
4

Hãy thử điều này:

>>> A = np.zeros((6,6)) 
>>> i,j = np.indices(A.shape) 
>>> z = [1, 2, 3, 4, 5] 

Bây giờ bạn có trực giác có thể truy cập bất kỳ đường chéo:

>>> A[i==j-1] = z 
>>> A 
array([[ 0., 1., 0., 0., 0., 0.], 
     [ 0., 0., 2., 0., 0., 0.], 
     [ 0., 0., 0., 3., 0., 0.], 
     [ 0., 0., 0., 0., 4., 0.], 
     [ 0., 0., 0., 0., 0., 5.], 
     [ 0., 0., 0., 0., 0., 0.]]) 

Trong cùng một cách bạn có thể gán mảng để A[i==j] vv

+0

Chưa so sánh hiệu suất với câu trả lời @ajcrs, nhưng tôi thích phần này để đơn giản. – FooBar

+0

@FooBar Phương pháp này chắc chắn là đơn giản hơn so với của tôi :-) Nhưng hiệu suất khôn ngoan, xây dựng một mặt nạ (với 'i == j-1') cho ma trận lớn hơn là không hiệu quả. Trên ma trận 1000x1000, việc đặt đường chéo trên đầu tiên chậm hơn khoảng 100 lần so với chỉ định trực tiếp các chỉ mục. Điều này là do bạn cần thực hiện một triệu '==' so sánh để xây dựng mặt nạ boolean (chưa kể đến việc có ma trận boolean lớn trong bộ nhớ). Dù điều này có quan trọng hay không phụ thuộc vào trường hợp sử dụng của bạn, tất nhiên. –

1

Đây là cách tiếp cận khác chỉ để cho vui. Bạn có thể viết chức năng đường chéo của riêng bạn để trả lại chế độ xem của đường chéo mà bạn cần.

import numpy as np 

def diag(a, k=0): 
    if k > 0: 
     a = a[:, k:] 
    elif k < 0: 
     a = a[-k:, :] 

    shape = (min(a.shape),) 
    strides = (sum(a.strides),) 
    return np.lib.stride_tricks.as_strided(a, shape, strides) 

a = np.arange(20).reshape((4, 5)) 
diag(a, 2)[:] = 88 
diag(a, -2)[:] = 99 
print(a) 
# [[ 0 1 88 3 4] 
# [ 5 6 7 88 9] 
# [99 11 12 13 88] 
# [15 99 17 18 19]] 
Các vấn đề liên quan