2013-03-01 40 views
5

Tôi có các mảng lớn nhưng thưa thớt và tôi muốn sắp xếp lại chúng bằng cách hoán đổi các hàng một cột. Cách tốt nhất để làm điều này trong scipy.sparse là gì?Sắp xếp lại các mảng thưa thớt bằng cách hoán đổi các hàng và cột

Một số vấn đề

  • Tôi không nghĩ rằng ma trận hoán vị là rất thích hợp cho công việc này, vì họ thích một cách ngẫu nhiên thay đổi cấu trúc thưa thớt. Và một thao tác sẽ luôn luôn 'nhân' tất cả các cột hoặc hàng, ngay cả khi chỉ có một vài hoán đổi cần thiết.

  • Biểu diễn ma trận thưa thớt tốt nhất trong scipy.sparse cho tác vụ này là gì?

  • Đề xuất thực hiện rất được hoan nghênh.

Tôi đã gắn thẻ thẻ này với Matlab, vì câu hỏi này có thể tìm thấy câu trả lời không nhất thiết phải là scipy cụ thể.

+0

Tôi cần điều này để thực hiện cụ thể. Tuy nhiên, như một đồng nghiệp đã chỉ ra cho tôi, nói chung, người ta sẽ không làm hoán vị trên một ma trận thưa thớt. Ma trận thưa thớt 'A' thường được sử dụng làm bản đồ tuyến tính' y = Axe', ví dụ: trong các giải pháp lặp lại. Do đó việc hoán đổi này được thực hiện tốt hơn bằng cách viết một trình bao bọc xung quanh 'A', hoán đổi các mục của vectơ đầu vào x (đây là cột hoán đổi trong' A') hoặc các mục của 'y' (đây là hoán đổi hàng). – Jan

Trả lời

4

CSC giữ một danh sách các chỉ mục hàng của tất cả các mục khác 0, định dạng CSR giữ một danh sách các chỉ mục cột của tất cả các mục khác 0. Tôi nghĩ bạn có thể tận dụng điều đó để trao đổi những thứ xung quanh như sau, và tôi nghĩ rằng không nên có bất kỳ tác dụng phụ với nó:

def swap_rows(mat, a, b) : 
    mat_csc = scipy.sparse.csc_matrix(mat) 
    a_idx = np.where(mat_csc.indices == a) 
    b_idx = np.where(mat_csc.indices == b) 
    mat_csc.indices[a_idx] = b 
    mat_csc.indices[b_idx] = a 
    return mat_csc.asformat(mat.format) 

def swap_cols(mat, a, b) : 
    mat_csr = scipy.sparse.csr_matrix(mat) 
    a_idx = np.where(mat_csr.indices == a) 
    b_idx = np.where(mat_csr.indices == b) 
    mat_csr.indices[a_idx] = b 
    mat_csr.indices[b_idx] = a 
    return mat_csr.asformat(mat.format) 

Bây giờ bạn có thể làm một cái gì đó như thế này:

>>> mat = np.zeros((5,5)) 
>>> mat[[1, 2, 3, 3], [0, 2, 2, 4]] = 1 
>>> mat = scipy.sparse.lil_matrix(mat) 
>>> mat.todense() 
matrix([[ 0., 0., 0., 0., 0.], 
     [ 1., 0., 0., 0., 0.], 
     [ 0., 0., 1., 0., 0.], 
     [ 0., 0., 1., 0., 1.], 
     [ 0., 0., 0., 0., 0.]]) 
>>> swap_rows(mat, 1, 3) 
<5x5 sparse matrix of type '<type 'numpy.float64'>' 
    with 4 stored elements in LInked List format> 
>>> swap_rows(mat, 1, 3).todense() 
matrix([[ 0., 0., 0., 0., 0.], 
     [ 0., 0., 1., 0., 1.], 
     [ 0., 0., 1., 0., 0.], 
     [ 1., 0., 0., 0., 0.], 
     [ 0., 0., 0., 0., 0.]]) 
>>> swap_cols(mat, 0, 4) 
<5x5 sparse matrix of type '<type 'numpy.float64'>' 
    with 4 stored elements in LInked List format> 
>>> swap_cols(mat, 0, 4).todense() 
matrix([[ 0., 0., 0., 0., 0.], 
     [ 0., 0., 0., 0., 1.], 
     [ 0., 0., 1., 0., 0.], 
     [ 1., 0., 1., 0., 0.], 
     [ 0., 0., 0., 0., 0.]]) 

Tôi đã sử dụng ma trận LIL để cho biết cách bạn có thể bảo toàn loại đầu ra của mình. Trong ứng dụng của bạn, bạn có thể muốn có định dạng CSC hoặc CSR và chọn xem có trao đổi các hàng hoặc cột đầu tiên dựa trên nó hay không, để giảm thiểu chuyển đổi.

+0

Cảm ơn @ Jaime, điều này có vẻ là những gì tôi đang tìm kiếm. Và nó cho thấy rằng tôi nên quen thuộc hơn với các định dạng thưa thớt. – Jan

+0

@Jan Bạn có thể muốn kiểm tra nó nhiều hơn một chút, tôi nghĩ rằng các ví dụ trên làm việc vì tất cả các mục khác 0 đều giống nhau. Tôi không có thời gian ngay bây giờ, nhưng sẽ xem xét chi tiết hơn sau. Có một mảng khác, 'mat.indptr', có thể cần một số thay đổi. [Các bài viết wikipedia trên định dạng thưa thớt Yale] (http://en.wikipedia.org/wiki/Sparse_matrix#Yale_format) có tất cả các thông tin cần thiết, trong trường hợp bạn muốn thử nó cho mình! – Jaime

+0

Tôi sẽ kiểm tra và cho bạn biết ... Cảm ơn nguồn. – Jan

0

Trong Matlab bạn có thể chỉ index các cột và các hàng theo cách bạn thích:

Matrix = speye(10); 
mycolumnorder = [1 2 3 4 5 6 10 9 8 7]; 
myroworder = [4 3 2 1 5 6 7 8 9 10]; 
Myorderedmatrix = Matrix(myroworder,mycolumnorder); 

Tôi nghĩ rằng đây bảo tồn thưa thớt ... Không biết về scipy dù ...

định dạng
Các vấn đề liên quan