簡體   English   中英

如何將頻率分布轉換為R中的概率分布

[英]How to convert frequency distribution to probability distribution in R

我有一個有n行觀察的矩陣。 觀察是特征的頻率分布。 我想將頻率分布轉換為概率分布,其中每行的總和為1.因此,矩陣中的每個元素應除以元素行的總和。

我編寫了以下R函數來完成工作,但是對於大型矩陣來說它非常慢:

prob_dist <- function(x) {

    row_prob_dist <- function(row) {
       return (t(lapply(row, function(x,y=sum(row)) x/y)))
       }

    for (i in 1:nrow(x)) {
       if (i==1) p_dist <- row_prob_dist(x[i,])
       else p_dist <- rbind(p_dist, row_prob_dist(x[i,]))
       }
    return(p_dist)
}

B = matrix(c(2, 4, 3, 1, 5, 7), nrow=3, ncol=2)
B
     [,1] [,2]
[1,]    2    1
[2,]    4    5
[3,]    3    7

prob_dist(B)
     [,1]      [,2]    
[1,] 0.6666667 0.3333333
[2,] 0.4444444 0.5555556
[3,] 0.3       0.7     

你能建議R功能完成這項工作和/或告訴我如何優化我的功能以更快地執行?

這是一次嘗試,但是在數據幀而不是矩陣上:

df <- data.frame(replicate(100,sample(1:10, 10e4, rep=TRUE)))

我嘗試了一種dplyr方法:

library(dplyr)
df %>% mutate(rs = rowSums(.)) %>% mutate_each(funs(. / rs), -rs) %>% select(-rs)

結果如下:

library(microbenchmark) 
mbm = microbenchmark(
dplyr = df %>% mutate(rs = rowSums(.)) %>% mutate_each(funs(. / rs), -rs) %>% select(-rs),
t = t(t(df) / rep(rowSums(df), each=ncol(df))),
apply = t(apply(df, 1, prop.table)),
times = 100
)

在此輸入圖像描述

#> mbm
#Unit: milliseconds
#  expr       min        lq      mean    median        uq       max neval
# dplyr  123.1894  124.1664  137.7076  127.3376  131.1523  445.8857   100
#     t  384.6002  390.2353  415.6141  394.8121  408.6669  787.2694   100
# apply 1425.0576 1520.7925 1646.0082 1599.1109 1734.3689 2196.5003   100

編輯 :@David基准測試更符合OP,所以我建議你考慮他的方法,如果你要使用矩陣。

沒有應用,一行中的矢量化解決方案:

t(t(B) / rep(rowSums(B), each=ncol(B)))
          [,1]      [,2]
[1,] 0.6666667 0.3333333
[2,] 0.4444444 0.5555556
[3,] 0.3000000 0.7000000

要么:

diag(1/rowSums(B)) %*% B

實際上我給了它一個快速思考,最好的歸化就是這么簡單

B/rowSums(B)
#           [,1]      [,2]
# [1,] 0.6666667 0.3333333
# [2,] 0.4444444 0.5555556
# [3,] 0.3000000 0.7000000

實際上@Stevens基准測試具有誤導性,因為OP有一個矩陣,而Steven基准測試數據框架。

是基質的基准。 因此對於矩陣,兩個矢量化解決方案都將優於dplyr ,后者不適用於矩陣

set.seed(123)
m <- matrix(sample(1e6), ncol = 100)

library(dplyr)
library(microbenchmark) 

Res <- microbenchmark(
  dplyr = as.data.frame(m) %>% mutate(rs = rowSums(.)) %>% mutate_each(funs(. / rs), -rs) %>% select(-rs),
  t = t(t(m) / rep(rowSums(m), each=ncol(m))),
  apply = t(apply(m, 1, prop.table)),
  DA = m/rowSums(m),
  times = 100
)

在此輸入圖像描述

我不確定你的函數是否有任何值,因為你可以使用histdensity函數來完成相同的結果。 此外, apply的使用將如上所述。 但它可以作為一個合理的編程示例。

您的代碼中存在一些效率低下的問題。

  • 你使用for循環而不是矢量化你的代碼。 這非常昂貴。 你應該使用上面評論中提到的申請。
  • 您正在使用rbind而不是為輸出預分配空間。 這也非常昂貴。

     out <- matrix(NA, nrow= n, ncol= ncol(B)) for (i in 1:nrow(B)) { out[i,] <- row_prob_dist(B[i,]) } 

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM