การปรับเมทริกซ์คอลัมน์แบบชาญฉลาดใน R [ปิด]


25

ฉันต้องการดำเนินการ normalization คอลัมน์ที่ชาญฉลาดของเมทริกซ์ในอาร์รับเมทริกซ์mฉันต้องการที่จะทำให้ปกติคอลัมน์แต่ละคอลัมน์โดยการหารแต่ละองค์ประกอบด้วยผลรวมของคอลัมน์ วิธีหนึ่ง (แฮ็ค) ที่ทำเช่นนี้มีดังนี้

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

มีวิธีสังเขป / ฉลาด / มีประสิทธิภาพมากขึ้นในการบรรลุภารกิจเดียวกันหรือไม่?

คำตอบ:


40

นี่คือสิ่งที่กวาดและขนาดสำหรับ

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

อีกวิธีหนึ่งคือคุณสามารถใช้การรีไซเคิล แต่คุณต้องเปลี่ยนมันสองครั้ง

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

หรือคุณสามารถสร้างเมทริกซ์เต็มรูปแบบที่คุณต้องการหารด้วยอย่างที่คุณทำในคำถามของคุณ นี่เป็นอีกวิธีที่คุณสามารถทำได้

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

และแจ้งให้ทราบล่วงหน้านอกจากนี้ caracal จากความคิดเห็น:

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

8
อีกหนึ่ง:m %*% diag(1/colSums(m))
caracal

ฉันไม่เคยได้ยินฟังก์ชั่นการกวาดมาก่อนขอบคุณมาก!
Matteo De Felice

10

อีกประการหนึ่งคือprop.table(m, 2)หรือเพียงแค่ว่าภายในการใช้งานpropr(m)sweep

อาจเป็นเรื่องที่น่าสนใจที่จะเปรียบเทียบประสิทธิภาพของโซลูชันที่เทียบเท่ากันเหล่านี้ดังนั้นฉันจึงทำเกณฑ์มาตรฐานเล็กน้อย (โดยใช้microbenchmarkแพ็คเกจ)

นี่คือเมทริกซ์อินพุตที่mฉันใช้:

          [,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

นี่คือการตั้งค่ามาตรฐาน:

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)

นี่คือผลลัพธ์ของการวัดประสิทธิภาพ:

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

เพื่อความสมบูรณ์นี่คือผลลัพธ์:

          [,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

ไม่ต้องสงสัยเลยว่าการฝึกซ้อม m / colSums(m)[col(m)] จะเป็นชัยชนะเล็กน้อย !


แต่สำหรับเมทริกซ์ใหญ่ ๆ ? ในตัวอย่างต่อมาฉันใช้เมทริกซ์ 1,000x1000

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

สำหรับเมทริกซ์ขนาดใหญ่ m / colSums(m)[col(m)] มีประสิทธิภาพดี (ตำแหน่งที่ 4) แต่ไม่ชนะ

สำหรับเมทริกซ์ที่ยิ่งใหญ่ m %*% diag(1/colSums(m)) ชนะ !


1
แพคเกจproprมาจากไหน?
Glen_b -Reinstate Monica

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

4
ยินดีต้อนรับสู่เว็บไซต์ @Smymyalyer คุณต้องการเพิ่มข้อความเพื่อแนะนำและอธิบายคำตอบของคุณให้ครบถ้วนมากขึ้นหรือไม่?
gung - Reinstate Monica
โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.