【问题标题】:Divide each each cell of large matrix by sum of its row将大矩阵的每个单元格除以其行的总和
【发布时间】:2016-06-11 23:59:13
【问题描述】:

我有一个按物种矩阵排列的站点。尺寸为 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
 }
}

【问题讨论】:

  • relative_abundance/rowSums(relative_abundance)?

标签: r matrix probability frequency


【解决方案1】:

您可以使用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))

这具有易于更改为按行运行的优点,但结果无论如何都会作为列连接,因此您必须转置它。

【讨论】:

  • 这就像一个魅力,但我不明白 apply() 如何知道如何将每个单元格 'i' 除以行的总和。因为在我的逻辑中i 引用了一个单元格,因此sum(i) 将返回单元格的总和而不是行的总和。
  • @Zane.Lazare apply 适用于行或列,这取决于我设置为2 的第二个参数,所以列。 i 代表一列,所以整列将除以它的和,并返回一个向量。 apply 自动将列重新绑定在一起,因此您将获得一个矩阵作为输出。
  • sweep 通常是这个的标准
【解决方案2】:

首先,你可以这样做

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

所以你不创建变量...

但要对其进行矢量化,我建议:使用 rowsum 函数(快速)计算行总和,然后您可以只使用按列应用,然后每个除以行和:

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

【讨论】:

  • relative_freq&lt;-apply(data,2,function(x) data[,x]/rowsum(data)) 不起作用,因为它rowsum(data) 抛出错误"Error in rowsum.default(data) : argument "group" is missing, with no default". 如果我定义grouping = row.names(),并设置reorder = FALSE,我最终会得到另一个错误"Error in Ops.data.frame(data[, x], rowsum(data, group = row.names(data), : ‘/’ only defined for equally-sized data frames"
【解决方案3】:

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

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))

然后从右边乘。

【讨论】:

    【解决方案4】:

    你可以这样做

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

    如果 relative_abundance 是矩阵而不是 data.frame,这会更快

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2014-04-06
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多