2012-02-25 40 views
15

Tôi đang cố gắng chia tỷ lệ các giá trị trong ma trận sao cho mỗi cột thêm tối đa một cột. Tôi đã thử:Chia cột bằng colSums trong R

m = matrix(c(1:9),nrow=3, ncol=3, byrow=T) 
    [,1] [,2] [,3] 
[1,] 1 2 3 
[2,] 4 5 6 
[3,] 7 8 9 

colSums(m) 
12 15 18 

m = m/colSums(m) 
      [,1]  [,2] [,3] 
[1,] 0.08333333 0.1666667 0.25 
[2,] 0.26666667 0.3333333 0.40 
[3,] 0.38888889 0.4444444 0.50 

colSums(m) 
[1] 0.7388889 0.9444444 1.1500000 

vì vậy rõ ràng điều này không hiệu quả. Sau đó tôi cố gắng này:

m = m/matrix(rep(colSums(m),3), nrow=3, ncol=3, byrow=T) 
      [,1]  [,2]  [,3] 
[1,] 0.08333333 0.1333333 0.1666667 
[2,] 0.33333333 0.3333333 0.3333333 
[3,] 0.58333333 0.5333333 0.5000000 

m = colSums(m) 
[1] 1 1 1 

để làm việc này, nhưng nó cảm thấy như tôi là thiếu một cái gì đó ở đây. Đây không thể là cách nó được thực hiện thường xuyên. Tôi chắc chắn tôi đang ngu ngốc ở đây. Bất kỳ giúp bạn có thể cung cấp sẽ được đánh giá Chúc mừng, Davy

Trả lời

38

Xem ?sweep, ví dụ:

> sweep(m,2,colSums(m),`/`) 
      [,1]  [,2]  [,3] 
[1,] 0.08333333 0.1333333 0.1666667 
[2,] 0.33333333 0.3333333 0.3333333 
[3,] 0.58333333 0.5333333 0.5000000 

hoặc bạn có thể transpose ma trận và sau đó colSums(m) được tái chế một cách chính xác. Đừng quên để transpose sau đó một lần nữa, như thế này:

> t(t(m)/colSums(m)) 
      [,1]  [,2]  [,3] 
[1,] 0.08333333 0.1333333 0.1666667 
[2,] 0.33333333 0.3333333 0.3333333 
[3,] 0.58333333 0.5333333 0.5000000 

Hoặc bạn sử dụng chức năng prop.table() làm về cơ bản giống nhau:

> prop.table(m,2) 
      [,1]  [,2]  [,3] 
[1,] 0.08333333 0.1333333 0.1666667 
[2,] 0.33333333 0.3333333 0.3333333 
[3,] 0.58333333 0.5333333 0.5000000 

Sự khác biệt thời gian khá nhỏ. hàm sweep() và thủ thuật t() là các giải pháp linh hoạt nhất, prop.table() chỉ dành cho trường hợp cụ thể này

+0

Brilliant. Cảm ơn bạn! Xấu hổ rằng tôi hoàn toàn quên mất 'prop.table()'. –

5

Bình thường, Joris có một câu trả lời tuyệt vời. Hai người khác mà đến tâm trí:

#Essentially your answer 
f1 <- function() m/rep(colSums(m), each = nrow(m)) 
#Two calls to transpose 
f2 <- function() t(t(m)/colSums(m)) 
#Joris 
f3 <- function() sweep(m,2,colSums(m),`/`) 

Joris' Câu trả lời là nhanh nhất trên máy tính của tôi:

> m <- matrix(rnorm(1e7), ncol = 10000) 
> library(rbenchmark) 
> benchmark(f1,f2,f3, replications=1e5, order = "relative") 
    test replications elapsed relative user.self sys.self user.child sys.child 
3 f3  100000 0.386 1.0000  0.385 0.001   0   0 
1 f1  100000 0.421 1.0907  0.382 0.002   0   0 
2 f2  100000 0.465 1.2047  0.386 0.003   0   0 
+1

Có vẻ như bài đăng của bạn và bản chỉnh sửa của tôi đã được chuyển sang nhau. Thx cho lời khen. –

+0

trừ khi bạn đang làm việc trên một tập dữ liệu khổng lồ, tôi thích 'sweep' cho tính biểu cảm của nó ... chỉ cho sự dễ thương, làm thế nào về' exp (scale (log (m), center = TRUE, scale = FALSE)) '(không phải là một ý tưởng tốt vì nhiều lý do!) –

+3

hoặc 'tỷ lệ (m, center = FALSE, scale = colSums (m))'. – flodel

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