Chuẩn hóa ma trận cột-khôn ngoan trong R [đóng]


25

Tôi muốn thực hiện chuẩn hóa cột theo ma trận trong R. Đưa ra một ma trận m, tôi muốn chuẩn hóa từng cột bằng cách chia mỗi phần tử cho tổng của cột. Một cách (hackish) để làm điều này là như sau:

m / t(replicate(nrow(m), colSums(m)))

Có cách nào ngắn gọn / thanh lịch / hiệu quả hơn để đạt được cùng một nhiệm vụ không?

Câu trả lời:


40

Đây là những gì quét và quy mô là cho.

sweep(m, 2, colSums(m), FUN="/")
scale(m, center=FALSE, scale=colSums(m))

Ngoài ra, bạn có thể sử dụng tái chế, nhưng bạn phải hoán chuyển nó hai lần.

t(t(m)/colSums(m))

Hoặc bạn có thể xây dựng ma trận đầy đủ mà bạn muốn chia cho, giống như bạn đã làm trong câu hỏi của mình. Đây là một cách khác bạn có thể làm điều đó.

m/colSums(m)[col(m)]

Và thông báo cũng bổ sung caracal từ các ý kiến:

m %*% diag(1/colSums(m))

8
Thêm một điều nữa:m %*% diag(1/colSums(m))
caracal

Tôi chưa bao giờ nghe nói về chức năng quét trước, cảm ơn!
Matteo De Felice

10

Khác là prop.table(m, 2), hoặc đơn giản propr(m), mà sử dụng nội bộ sweep.

Nó có thể được quan tâm để so sánh hiệu suất của các giải pháp tương đương này, vì vậy tôi đã làm một điểm chuẩn nhỏ (sử dụng microbenchmarkgói).

Đây là ma trận đầu vào mtôi đã sử dụng:

          [,1]         [,2]         [,3]         [,4]         [,5]
A 1.831564e-02 4.978707e-02 1.353353e-01 3.678794e-01 3.678794e-01
B 3.678794e-01 1.353353e-01 4.978707e-02 1.831564e-02 6.737947e-03
C 4.539993e-05 2.061154e-09 9.357623e-14 4.248354e-18 5.242886e-22
D 1.831564e-02 4.978707e-02 1.353353e-01 3.678794e-01 3.678794e-01
E 3.678794e-01 1.353353e-01 4.978707e-02 1.831564e-02 6.737947e-03
F 4.539993e-05 2.061154e-09 9.357623e-14 4.248354e-18 5.242886e-22
G 1.831564e-02 4.978707e-02 1.353353e-01 3.678794e-01 3.678794e-01
H 3.678794e-01 1.353353e-01 4.978707e-02 1.831564e-02 6.737947e-03
I 4.539993e-05 2.061154e-09 9.357623e-14 4.248354e-18 5.242886e-22

Đây là thiết lập điểm chuẩn:

microbenchmark(
prop = prop.table(m, 2),
scale = scale(m, center=FALSE, scale=colSums(m)),
sweep = sweep(m, 2, colSums(m), FUN="/"),
t_t_colsums = t(t(m)/colSums(m)),
m_colsums_col = m/colSums(m)[col(m)],
m_mult_diag = m %*% diag(1/colSums(m)),
times = 1500L)

Đây là kết quả của điểm chuẩn:

Unit: microseconds
           expr     min       lq   median       uq      max
1 m_colsums_col  29.089  32.9565  35.9870  37.5215 1547.972
2   m_mult_diag  43.278  47.6115  51.7075  53.8945  110.560
3          prop 207.070 214.3010 216.6800 219.9680 2091.913
4         scale 133.659 142.6325 145.3100 147.9195 1730.640
5         sweep 113.969 119.6315 121.3725 123.6570 1663.356
6   t_t_colsums  56.976  65.3580  67.8895  69.5130 1640.660

Để đầy đủ, đây là đầu ra:

          [,1]         [,2]         [,3]         [,4]         [,5]
A 1.580677e-02 8.964714e-02 2.436862e-01 3.175247e-01 3.273379e-01
B 3.174874e-01 2.436862e-01 8.964714e-02 1.580862e-02 5.995403e-03
C 3.918106e-05 3.711336e-09 1.684944e-13 3.666847e-18 4.665103e-22
D 1.580677e-02 8.964714e-02 2.436862e-01 3.175247e-01 3.273379e-01
E 3.174874e-01 2.436862e-01 8.964714e-02 1.580862e-02 5.995403e-03
F 3.918106e-05 3.711336e-09 1.684944e-13 3.666847e-18 4.665103e-22
G 1.580677e-02 8.964714e-02 2.436862e-01 3.175247e-01 3.273379e-01
H 3.174874e-01 2.436862e-01 8.964714e-02 1.580862e-02 5.995403e-03
I 3.918106e-05 3.711336e-09 1.684944e-13 3.666847e-18 4.665103e-22

Không có nghi ngờ cho chiến thắng nhỏ ma m / colSums(m)[col(m)] trận !


Nhưng đối với ma trận lớn? Trong ví dụ tiếp theo, tôi đã sử dụng ma trận 1000x1000.

set.seed(42)
m <- matrix(sample(1:10, 1e6, TRUE), 1e3)
...
Unit: milliseconds
           expr      min       lq   median        uq       max
1 m_colsums_col 55.26442 58.94281 64.41691 102.69683 119.08685
2   m_mult_diag 34.67692 41.68494 80.05480  89.48099  99.72062
3          prop 87.95552 94.13143 99.17044 136.03669 160.51586
4         scale 52.84534 55.07107 60.57154  99.87761 156.16622
5         sweep 52.79542 55.93877 61.55066  99.67766 119.05134
6   t_t_colsums 63.09783 65.53783 68.93731 110.03691 127.89792

Đối với ma trận lớn hoạt m / colSums(m)[col(m)] động tốt (vị trí thứ 4) nhưng không giành chiến thắng .

Đối với ma trận lớn m %*% diag(1/colSums(m)) chiến thắng !


1
gói proprtừ đâu
Glen_b -Reinstate Monica

5
apply(m,2,norm<-function(x){return (x/sum(x)}) ?

4
Chào mừng đến với trang web, @Sowmyalyer. Bạn có phiền khi thêm một số văn bản để giới thiệu và giải thích câu trả lời của bạn đầy đủ hơn?
gung - Phục hồi Monica
Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.