2010-09-04 67 views
56

Tôi đang tối ưu hóa một hàm và tôi muốn loại bỏ các vòng lặp chậm. Tôi đang tìm một cách nhanh hơn để nhân mỗi hàng của một ma trận bằng một vectơ.Nhân các hàng ma trận theo vectơ?

Bất kỳ ý tưởng nào?

EDIT:

Tôi không tìm kiếm phép nhân "cổ điển".

Ví dụ: Tôi có ma trận có 23 cột và 25 hàng và một vectơ có độ dài 23. Kết quả là tôi muốn có ma trận 25x23 có mỗi hàng nhân với véc-tơ.

Trả lời

58

Tôi nghĩ bạn đang tìm kiếm sweep().

> (mat <- matrix(rep(1:3,each=5),nrow=3,ncol=5,byrow=TRUE)) 
    [,1] [,2] [,3] [,4] [,5] 
[1,] 1 1 1 1 1 
[2,] 2 2 2 2 2 
[3,] 3 3 3 3 3 
> vec <- 1:5 
> sweep(mat,MARGIN=2,vec,`*`) 
    [,1] [,2] [,3] [,4] [,5] 
[1,] 1 2 3 4 5 
[2,] 2 4 6 8 10 
[3,] 3 6 9 12 15 

Đây là một trong những chức năng cốt lõi của R, mặc dù các cải tiến đã được thực hiện trên nhiều năm.

31
> MyMatrix <- matrix(c(1,2,3, 11,12,13), nrow = 2, ncol=3, byrow=TRUE) 
> MyMatrix 
    [,1] [,2] [,3] 
[1,] 1 2 3 
[2,] 11 12 13 
> MyVector <- c(1:3) 
> MyVector 
[1] 1 2 3 

Bạn có thể sử dụng một trong hai:

> t(t(MyMatrix) * MyVector) 
    [,1] [,2] [,3] 
[1,] 1 4 9 
[2,] 11 24 39 

hay:

> MyMatrix %*% diag(MyVector) 
    [,1] [,2] [,3] 
[1,] 1 4 9 
[2,] 11 24 39 
-2

Google "R ma trận multiplcation" Năng suất Matrix Multiplication, trong đó mô tả% nhà điều hành% * và nói "sẽ nhân đôi hai ma trận Nếu một đối số là một vectơ, nó sẽ được đẩy lên một ma trận hàng hoặc cột để làm cho hai đối số phù hợp, nếu cả hai đều là vectơ, nó sẽ trả về p bên trong roduct (như một ma trận). "

+2

Câu hỏi đặt ra đã không được – MHH

21

Trên thực tế, sweep không phải là lựa chọn nhanh nhất trên máy tính của tôi:

MyMatrix <- matrix(c(1:1e6), ncol=1e4, byrow=TRUE) 
MyVector <- c(1:1e4) 

Rprof(tmp <- tempfile(),interval = 0.001) 
t(t(MyMatrix) * MyVector) # first option 
Rprof() 
MyTimerTranspose=summaryRprof(tmp)$sampling.time 
unlink(tmp) 

Rprof(tmp <- tempfile(),interval = 0.001) 
MyMatrix %*% diag(MyVector) # second option 
Rprof() 
MyTimerDiag=summaryRprof(tmp)$sampling.time 
unlink(tmp) 

Rprof(tmp <- tempfile(),interval = 0.001) 
sweep(MyMatrix ,MARGIN=2,MyVector,`*`) # third option 
Rprof() 
MyTimerSweep=summaryRprof(tmp)$sampling.time 
unlink(tmp) 

Rprof(tmp <- tempfile(),interval = 0.001) 
t(t(MyMatrix) * MyVector) # first option again, to check order 
Rprof() 
MyTimerTransposeAgain=summaryRprof(tmp)$sampling.time 
unlink(tmp) 

MyTimerTranspose 
MyTimerDiag 
MyTimerSweep 
MyTimerTransposeAgain 

sản lượng này:

> MyTimerTranspose 
[1] 0.04 
> MyTimerDiag 
[1] 40.722 
> MyTimerSweep 
[1] 33.774 
> MyTimerTransposeAgain 
[1] 0.043 

Trên hết là tùy chọn thấp nhất, tùy chọn thứ hai đạt đến giới hạn bộ nhớ (2046 MB). Tuy nhiên, xem xét các tùy chọn còn lại, chuyển đổi kép đôi có vẻ tốt hơn rất nhiều so với sweep theo ý kiến ​​của tôi.


Sửa

Chỉ cần cố gắng dữ liệu nhỏ hơn một số lặp đi lặp lại lần: "làm thế nào để bạn nhân một ma trận bởi một vector"

MyMatrix <- matrix(c(1:1e3), ncol=1e1, byrow=TRUE) 
MyVector <- c(1:1e1) 
n=100000 

[...] 

for(i in 1:n){ 
# your option 
} 

[...] 

> MyTimerTranspose 
[1] 5.383 
> MyTimerDiag 
[1] 6.404 
> MyTimerSweep 
[1] 12.843 
> MyTimerTransposeAgain 
[1] 5.428 
+3

Theo kinh nghiệm của tôi, nếu bạn ném một loạt 'NA' vào ma trận, thời gian được thực hiện bởi 'diag' dường như đi qua mái nhà. Đối với một 1E4x1E4 mat chứa 1E5 'NA', tôi có được: 'MyTimerTranspose' = 0.014,' MyTimerSweep' = 0.042, 'MyTimerDiag' = 67.738. Tôi muốn tái tạo, nhưng tôi thiếu kiên nhẫn ... chỉ cần một cái gì đó để ghi nhớ. – jbaums

+0

Tôi thực sự thích câu trả lời chuyển vị kép, chủ yếu là vì nó cho thấy câu trả lời là gì nếu chúng ta thay thế "hàng" bằng "cột", làm cho câu trả lời nhỏ gọn A * x, không rõ ràng trừ khi bạn thực sự hiểu cách R làm việc với ma trận. – MHH

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