2011-08-23 37 views
6

Giả sử tôi có ma trận dữ liệu thưa thớt thực sự lớn, nhưng tôi chỉ quan tâm đến việc xem mẫu của nó làm cho nó trở nên thưa thớt hơn. Giả sử tôi cũng có một khung dữ liệu của bộ ba bao gồm các cột cho hàng/cột/giá trị của dữ liệu (được nhập từ tệp csv). Tôi biết tôi có thể sử dụng sparseMatrix() chức năng của thư viện (Matrix) để tạo ra một ma trận thưa thớt sử dụngThêm giá trị vào ma trận bằng cách sử dụng các chỉ mục bao gồm tên hàng và cột

sparseMatrix(i=df$row,j=df$column,x=df$value) 

Tuy nhiên, do giá trị của tôi, tôi kết thúc với một ma trận thưa thớt đó là hàng triệu hàng bởi hàng chục ngàn cột (hầu hết trong số đó trống vì tập hợp con của tôi loại trừ hầu hết các hàng và cột). Tất cả những hàng và cột bằng 0 này đều kết thúc một số chức năng của tôi (lấy phân cụm ví dụ - tôi kết thúc với một cụm bao gồm nguồn gốc khi nguồn gốc không phải là điểm hợp lệ). Tôi muốn thực hiện thao tác tương tự, nhưng sử dụng i và j làm tên và tên. Tôi đã cố gắng tạo ra một vector dày đặc, lấy mẫu xuống đến kích thước tối đa và thêm giá trị sử dụng

denseMatrix <- matrix(0,nrows,ncols,dimnames=c(df$row,df$column)) 
denseMatrix[as.character(df$row),as.character(df$column)]=df$value 

(thực sự tôi đã thiết lập nó bằng 1 vì tôi không quan tâm đến giá trị trong trường hợp này) nhưng tôi đã tìm thấy nó lấp đầy trong toàn bộ ma trận bởi vì nó có thập tự giá của tất cả các hàng và cột hơn là chỉ row1 * col1, row2 * col2 ... Có ai biết một cách để thực hiện những gì tôi đang cố gắng làm gì? Ngoài ra tôi sẽ được tốt với điền vào một ma trận thưa thớt và chỉ đơn giản là có nó bằng cách nào đó loại bỏ tất cả các hàng không và cột để nhỏ gọn chính nó vào một hình thức dày đặc hơn (nhưng tôi muốn duy trì một số tài liệu tham khảo trở lại số hàng và cột ban đầu) Tôi đánh giá cao mọi đề xuất!

Dưới đây là một ví dụ:

> rows<-c(3,1,3,5) 
> cols<-c(2,4,6,6) 
> mtx<-sparseMatrix(i=rows,j=cols,x=1) 
> mtx 
5 x 6 sparse Matrix of class "dgCMatrix" 

[1,] . . . 1 . . 
[2,] . . . . . . 
[3,] . 1 . . . 1 
[4,] . . . . . . 
[5,] . . . . . 1 

Tôi muốn thoát khỏi colums 1,3 và 5 cũng như hàng 2 và 4. Đây là một ví dụ khá tầm thường, nhưng hãy tưởng tượng nếu thay vì phải số hàng 1, 3 và 5 là 1000, 3000 và 5000. Sau đó sẽ có nhiều hàng trống hơn giữa chúng. Đây là những gì xảy ra khi tôi sử dụng một ma trận dày đặc với tên hàng/cột

> dmtx<-matrix(0,3,3,dimnames=list(c(1,3,5),c(2,4,6))) 
> dmtx 
    2 4 6 
1 0 0 0 
3 0 0 0 
5 0 0 0 
> dmtx[as.character(rows),as.character(cols)]=1 
> dmtx 
    2 4 6 
1 1 1 1 
3 1 1 1 
5 1 1 1 
+0

Bạn có thể hiển thị một ví dụ nhỏ, nói 10x10, ma trận thưa thớt, cộng với ba bạn có thể sử dụng trong tình huống đó và tập hợp con nào bạn muốn? –

+1

Bạn đã điều tra gói SparseM chưa? – Spacedman

+0

Tôi đang thêm một ví dụ trên – dscheffy

Trả lời

4

Khi bạn nói "thoát khỏi" cột nhất định/hàng, bạn có nghĩa chỉ này:

> mtx[-c(2,4), -c(1,3,5)] 
3 x 3 sparse Matrix of class "dgCMatrix" 

[1,] . 1 . 
[2,] 1 . 1 
[3,] . . 1 

công trình Subsetting, vì vậy bạn chỉ cần một cách để tìm ra hàng và cột nào trống? Nếu đúng, thì bạn có thể sử dụng colSums()rowSums() vì chúng đã được tăng cường bởi gói Ma trận để có các phương pháp thích hợp cho ma trận thưa thớt. Điều này sẽ giữ gìn thưa thớt trong khi phẫu thuật

> dimnames(mtx) <- list(letters[1:5], LETTERS[1:6]) 
> mtx[which(rowSums(mtx) != 0), which(colSums(mtx) != 0)] 
3 x 3 sparse Matrix of class "dgCMatrix" 
    B D F 
a . 1 . 
c 1 . 1 
e . . 1 

hoặc, có lẽ an toàn hơn

> mtx[rowSums(mtx) != 0, colSums(mtx) != 0] 
3 x 3 sparse Matrix of class "dgCMatrix" 
    B D F 
a . 1 . 
c 1 . 1 
e . . 1 
+0

giải pháp của bạn chiếm ưu thế của tôi, tôi đã xóa của tôi ... –

4

Mã của bạn gần như hoạt động, bạn chỉ cần cbind ghép tên hàng và tên cột. Mỗi hàng của ma trận kết quả được xử lý như một cặp thay vì xử lý các hàng và các cột riêng biệt.

> dmtx <- matrix(0,3,3,dimnames=list(c(1,3,5),c(2,4,6))) 
> dmtx[cbind(as.character(rows),as.character(cols))] <- 1 
> dmtx 
    2 4 6 
1 0 1 0 
3 1 0 1 
5 0 0 1 

Điều này có thể nhanh hơn nếu bạn sử dụng các yếu tố.

> rowF <- factor(rows) 
> colF <- factor(cols) 
> dmtx <- matrix(0, nlevels(rowF), nlevels(colF), 
       dimnames=list(levels(rowF), levels(colF))) 
> dmtx[cbind(rowF,colF)] <- 1 
> dmtx 
    2 4 6 
1 0 1 0 
3 1 0 1 
5 0 0 1 

Bạn cũng có thể sử dụng các yếu tố này trong một cuộc gọi đến sparseMatrix.

> sparseMatrix(i=as.integer(rowF), j=as.integer(colF), x=1, 
+    dimnames = list(levels(rowF), levels(colF))) 
3 x 3 sparse Matrix of class "dgCMatrix" 
    2 4 6 
1 . 1 . 
3 1 . 1 
5 . . 1 

Lưu ý rằng một trong các giải pháp khác có thể nhanh hơn; chuyển đổi thành các yếu tố có thể chậm nếu có nhiều dữ liệu.

+0

Drat, tôi không nên có dithered quá lâu, bạn chỉ cần đánh bại tôi! – joran

+0

Xin cảm ơn! Các trang trợ giúp rất tuyệt vời khi bạn tìm kiếm một hàm, không hữu ích khi cú pháp cơ bản của lõi ... Tôi nhận được nó ngay bây giờ, hai vectơ sẽ giúp bạn trở thành một submatrix - tôi đã trỏ đến submatrix đó là đầy đủ ma trận. Tốt để biết rằng cbinding hai vectơ về cơ bản sẽ cho tôi vectorize hoạt động. Tôi vẫn biết R, nhưng học nhanh ... – dscheffy

1

Vấn đề đầu tiên của bạn xuất phát từ thực tế là coordinate list (COO) có các giá trị không tiếp giáp đối với chỉ mục hàng và cột. Khi phải đối mặt với điều này, hoặc thậm chí khi giao dịch với hầu hết các ma trận thưa thớt, tôi có xu hướng sắp xếp lại các hàng và cột theo sự hỗ trợ của chúng.

Bạn có thể làm điều này theo hai cách:

  1. Sản xuất ma trận thưa thớt và làm colSumsrowSums của logical(yourMatrix) để có được những giá trị hỗ trợ, hoặc
  2. Sử dụng một chức năng như table hay bigtabulate (từ bigmemory bộ) để tính số lần duy nhất mà mỗi giá trị đã xảy ra trong danh sách tọa độ. (Sở thích của tôi là bigtabulate.)

Một khi bạn có sự hỗ trợ, bạn có thể sử dụng chức năng rank (trên thực tế, rank(-1 * support, ties = "first")) để lập bản đồ các chỉ số ban đầu cho những người mới, dựa trên cấp bậc của họ.

Tại thời điểm này, nếu bạn tạo ma trận với sparseMatrix, nó sẽ chỉ tạo một ma trận có kích thước sao cho tất cả các hàng và cột của bạn có hỗ trợ. Nó sẽ không ánh xạ tới bất cứ thứ gì lớn hơn.

Điều này tương tự như cách tiếp cận của @ GavinSimpson, mặc dù phương pháp của ông chỉ giảm hàng và cột bị thiếu, trong khi cách tiếp cận của tôi đặt lại mật độ tối đa ở góc trên bên trái của ma trận, với mật độ giảm khi bạn chuyển sang chỉ mục lớn hơn cho các hàng và cột. Để ánh xạ trở lại các chỉ mục ban đầu trong cách tiếp cận của tôi, chỉ cần tạo một cặp ánh xạ: "gốc để xếp hạng" và "xếp hạng thành bản gốc" và bạn có thể tạo lại hoàn toàn dữ liệu gốc nếu bạn chọn.

0

@ Câu trả lời của Iterator rất hữu ích cho ứng dụng của tôi, nhưng thật đáng tiếc là phản ứng của anh ta/cô ấy không bao gồm ví dụ minh họa ý tưởng. Đây là việc tôi triển khai ý tưởng sắp xếp lại các hàng và cột của ma trận thưa thớt rất lớn (ví dụ: với khoảng một triệu hàng và một vài nghìn cột trên siêu máy tính có đủ bộ nhớ để tải ma trận thưa thớt).

library(Matrix) 

sparseY <- sparseMatrix(i=sample(2000, 500, replace=TRUE), j=sample(1000,500, replace=TRUE), x=sample(10000,500)) 

# visualize the original sparse matrix 
image(sparseY, aspect=1, colorkey=TRUE, main="The original sparse matrix") 

numObs <- length([email protected]) 
# replace all non-zero entries with 1 to calculate #non-zero entries per row/column and use rank() to sort based on supports 
logicalY <- sparseY; [email protected] <- rep(1, numObs) 

# calculate the number of observed entries per row/column 
colObsFreqs <- colSums(logicalY) 
rowObsFreqs <- rowSums(logicalY) 

colObsFreqs 
rowObsFreqs 

# get the rank of supports for rows and columns 
colRanks <- rank(-1*colObsFreqs, ties="first") 
rowRanks <- rank(-1*rowObsFreqs, ties="first") 

# Sort the ranks from small to large 
sortColInds <- sort(colRanks, index.return=TRUE) 
sortRowInds <- sort(rowRanks, index.return=TRUE) 

# reorder the original sparse matrix so that the maximum density data block is placed in the upper left corner of the matrix, with decreasing density as you move to larger indices for the rows and columns. 
sparseY <- sparseY[ sortRowInds$ix, sortColInds$ix ] 

# visualize the reordered sparse matrix 
image(sparseY, aspect=1, colorkey=TRUE, main="The sparse matrix after reordering") 

logicalY <- sparseY; [email protected] <- rep(1, numObs) 
# Check whether the resulting sparse matrix is what's expected, i.e. with the maximum density data block placed in the upper left corner of the matrix 
colObsFreqs <- colSums(logicalY) 
rowObsFreqs <- rowSums(logicalY) 

colObsFreqs 
rowObsFreqs 
Các vấn đề liên quan