2011-01-14 15 views
26

Giả sử tôi có ma trận NxN M (lil_matrix hoặc csr_matrix) từ scipy.sparse và tôi muốn biến nó thành (N + 1) xN trong đó M_modified [i, j] = M [i, j] cho 0 < = i < N (và tất cả j) và M [N, j] = 0 cho tất cả j. Về cơ bản, tôi muốn thêm một hàng số 0 vào cuối M và giữ phần còn lại của ma trận. Có cách nào để làm điều này mà không sao chép dữ liệu?mở rộng (thêm hàng hoặc cột) ma trận scipy.sparse

Trả lời

4

Tôi không nghĩ rằng có bất kỳ cách nào để thực sự thoát khỏi việc sao chép. Cả hai loại ma trận thưa thớt này lưu trữ dữ liệu của chúng dưới dạng mảng Numpy (trong thuộc tính dữ liệu và chỉ mục cho csr và trong thuộc tính dữ liệu và hàng cho lil) trong nội bộ và mảng Numpy không thể mở rộng được.

Cập nhật với nhiều thông tin:

LIL không đại diện cho danh sách liên kết, nhưng việc thực hiện hiện nay không hoàn toàn sống theo tên. Các mảng Numpy được sử dụng cho datarows đều là đối tượng kiểu. Mỗi đối tượng trong các mảng này thực sự là các danh sách Python (một danh sách rỗng khi tất cả các giá trị bằng không trong một hàng). Các danh sách Python không phải là danh sách được liên kết chính xác, nhưng chúng gần giống và khá thẳng thắn là một lựa chọn tốt hơn do O (1) tra cứu. Cá nhân, tôi không ngay lập tức thấy điểm của việc sử dụng một mảng Numpy của các đối tượng ở đây chứ không chỉ là một danh sách Python. Bạn có thể dễ dàng thay đổi việc triển khai thực hiện lil hiện tại để sử dụng các danh sách Python thay vào đó sẽ cho phép bạn thêm một hàng mà không cần sao chép toàn bộ ma trận.

+0

Nếu nó đủ quan trọng đối với ứng dụng của bạn, bạn có thể triển khai một lớp mới với giao diện scipy.sparse sử dụng loại dữ liệu dễ mở rộng hơn dưới mui xe. –

+1

Có lẽ ai đó có kiến ​​thức sâu hơn về cấu trúc dữ liệu cơ bản có thể trả lời câu hỏi này. Tôi nghĩ lil_matrix đã được triển khai với danh sách liên kết? – RandomGuy

+0

@scandido, xem phần bổ sung mới nhất của tôi có trả lời câu hỏi của bạn hay không. –

8

Không chắc chắn nếu bạn vẫn đang tìm kiếm giải pháp, nhưng có thể những người khác có thể xem xét hstackvstack - http://docs.scipy.org/doc/scipy/reference/generated/scipy.sparse.hstack.html. Tôi nghĩ rằng chúng tôi có thể xác định một csr_matrix cho hàng bổ sung duy nhất và sau đó vstack nó với ma trận trước đó.

+0

[mã nguồn cho vstack] (https://github.com/scipy/scipy/blob/v0.19.0/scipy/sparse/construct.py#L461-L492) Như điều này ngụ ý, nó trả về một bản sao mới của đầu vào ma trận, do đó không đủ hiệu quả nếu chúng ta muốn mở rộng ma trận ** tại chỗ **. – JenkinsY

24

Scipy không có cách nào để thực hiện việc này mà không sao chép dữ liệu nhưng bạn có thể tự làm bằng cách thay đổi các thuộc tính xác định ma trận thưa thớt.

Có 4 thuộc tính tạo nên csr_matrix:

dữ liệu: Một mảng chứa các giá trị thực tế trong ma trận

chỉ số: một mảng chứa các chỉ số cột tương ứng với mỗi giá trị trong dữ liệu

indptr: Một mảng chỉ định chỉ mục trước giá trị đầu tiên trong dữ liệu cho mỗi hàng. Nếu hàng trống thì chỉ mục giống với cột trước đó.

hình dạng: Một tuple chứa hình dạng của ma trận

Nếu bạn chỉ đơn giản là thêm một dãy số không để phía dưới tất cả các bạn phải làm là thay đổi hình dạng và indptr cho ma trận của bạn.

x = np.ones((3,5)) 
x = csr_matrix(x) 
x.toarray() 
>> array([[ 1., 1., 1., 1., 1.], 
      [ 1., 1., 1., 1., 1.], 
      [ 1., 1., 1., 1., 1.]]) 
# reshape is not implemented for csr_matrix but you can cheat and do it yourself. 
x._shape = (4,5) 
# Update indptr to let it know we added a row with nothing in it. So just append the last 
# value in indptr to the end. 
# note that you are still copying the indptr array 
x.indptr = np.hstack((x.indptr,x.indptr[-1])) 
x.toarray() 
array([[ 1., 1., 1., 1., 1.], 
     [ 1., 1., 1., 1., 1.], 
     [ 1., 1., 1., 1., 1.], 
     [ 0., 0., 0., 0., 0.]]) 

Đây là chức năng xử lý trường hợp tổng quát hơn của vstacking bất kỳ 2 csr_matrices nào. Bạn vẫn kết thúc sao chép các mảng cứng nhắc cơ bản nhưng nó vẫn nhanh hơn đáng kể so với phương pháp vstack scipy.

def csr_vappend(a,b): 
    """ Takes in 2 csr_matrices and appends the second one to the bottom of the first one. 
    Much faster than scipy.sparse.vstack but assumes the type to be csr and overwrites 
    the first matrix instead of copying it. The data, indices, and indptr still get copied.""" 

    a.data = np.hstack((a.data,b.data)) 
    a.indices = np.hstack((a.indices,b.indices)) 
    a.indptr = np.hstack((a.indptr,(b.indptr + a.nnz)[1:])) 
    a._shape = (a.shape[0]+b.shape[0],b.shape[1]) 
    return a 
+1

Tôi nghĩ rằng bạn có thể lấy đi ngay cả khi không trả về 'a', vì các đối số hàm được truyền qua tham chiếu,' a' được sửa đổi trực tiếp ngay cả trong phạm vi hàm. Ngoài ra, có thể có một tương tự csc_happend (a, b)? – richizy

+0

Ý tưởng hay, chỉ cần đặt lại hình dạng. – Jan