将每个大矩阵的每个单元除以其行的总和

时间:2016-02-29 02:53:57

标签: r matrix probability frequency relative

我有一个物种矩阵的网站。尺寸为375 x 360.每个值代表该场地样本中物种的频率。

我正在尝试将此矩阵从频率转换为每个站点的相对丰度。

我已经尝试了几种方法来实现这一点,唯一有效的方法是使用for循环。但是,这需要非常长的时间,或者根本就没有完成。

是否有功能或矢量化方法来实现这一目标?我已经将我的for循环作为我想要做的一个例子。

relative_abundance <- matrix(0, nrow= nrow(data_wide),
ncol=ncol(data), dimnames = dimnames(data))

i=0
j=0

for(i in 1:nrow(relative_abundance)){
  for(j in 1:ncol(relative_abundance)){
    species_freq <- data[i,j]
    row_sum <- sum(data[i,])
    relative_abundance[i,j] <- species_freq/row_sum
 }
}

4 个答案:

答案 0 :(得分:6)

您可以使用apply执行此操作,但在这种情况下scale会使事情变得更加简单。假设您想要按列总和来划分列:

set.seed(0)
relative_abundance <- matrix(sample(1:10, 360*375, TRUE), nrow= 375)

freqs <- scale(relative_abundance, center = FALSE, 
               scale = colSums(relative_abundance))

矩阵太大了,无法在这里输出,但这就是它的样子:

> head(freqs[, 1:5])
            [,1]         [,2]        [,3]        [,4]         [,5]
[1,] 0.004409603 0.0014231499 0.003439803 0.004052685 0.0024026910
[2,] 0.001469868 0.0023719165 0.002457002 0.005065856 0.0004805382
[3,] 0.001959824 0.0018975332 0.004914005 0.001519757 0.0043248438
[4,] 0.002939735 0.0042694497 0.002948403 0.002532928 0.0009610764
[5,] 0.004899559 0.0009487666 0.000982801 0.001519757 0.0028832292
[6,] 0.001469868 0.0023719165 0.002457002 0.002026342 0.0009610764

理智检查:

> head(colSums(freqs))
[1] 1 1 1 1 1 1

使用apply

freqs2 <- apply(relative_abundance, 2, function(i) i/sum(i))

这样可以轻松地按行运行,但结果将以列的形式连接,因此您必须转置它。

答案 1 :(得分:2)

使用一些简单的线性代数,我们可以产生更快的结果。只需在左侧乘以对角矩阵,并使用您需要的缩放系数,如下所示:

library(Matrix)
set.seed(0)
relative_abundance <- matrix(sample(1:10, 360*375, TRUE), nrow= 375)
Diagonal_Matrix <- diag(1/rowSums(relative_abundance))

然后我们从左边乘以:

row_normalized_matrix <- Diagonal_Matrix %*% relative_abundance

如果要按列标准化,只需输入:

Diagonal_Matrix <- diag(1/colSums(relative_abundance))

并从右边相乘。

答案 2 :(得分:0)

首先,你可以做到

relative_abundance[i,j] <- data[i,j]/sum(data[i,])

所以你不要创建变量......

但是为了矢量化它,我建议:用rowum函数(快速)计算行和,然后你可以使用apply by columns,每个除以rowsums:

 relative_freq<-apply(data,2,function(x) data[,x]/rowsum(data)) 

答案 3 :(得分:0)

您可以这样做

relative_abundance <- matrix(sample(1:10, 360*375, TRUE), nrow= 375)
datnorm <- relative_abundance/rowSums(relative_abundance) 

如果relative_abundance是矩阵而不是data.frame,则速度会更快