【问题标题】:How can I build a for-loop that sums n rows from a super matrix and results in a cumulative matrix?如何构建一个 for 循环,对超矩阵中的 n 行求和并生成累积矩阵?
【发布时间】:2022-01-15 07:52:22
【问题描述】:

我在 R 中有一个 68 列和近 43000 行的矩阵。它基本上是一个由较小的 68*68 矩阵组成的巨大矩阵。我需要得到每 15 个较小矩阵的平均矩阵(因为每 15 个矩阵等于一个参与者)。所以行 1-68、69-136 等直到 1020 (=15* 68)。我不知道如何制作一个 for 循环,它需要每 68 行并将其与下一个 68 等相加,同时仍保持 68 * 68 矩阵。我能够正确总结它们的唯一方法是对特定行编制索引,但由于我有 43000 行,而这个数据集是 30 多个文件中的第一个,我不想继续编制索引。

谁能帮我找到一个简单/快速的方法来做到这一点?

编辑:所以数据的一个例子是:

print(Matrix_Alpha_ami[1:3,1:5])
V1     V2     V3     V4     V5
[1,] 0.0000 0.4749 0.5629 0.6339 0.5406
[2,] 0.4749 0.0000 0.3157 0.5234 0.4737
[3,] 0.5629 0.3157 0.0000 0.5707 0.4191

> print(Matrix_Alpha_ami[69:71,1:5])
         V1     V2     V3     V4     V5
[69,] 0.0000 0.4993 0.4812 0.5227 0.5018
[70,] 0.4993 0.0000 0.5444 0.6106 0.3324
[71,] 0.4812 0.5444 0.0000 0.5818 0.4107

列一直持续到 V68,行下降到 42k+

数据的第一位是矩阵 1 的开头,矩阵 2 的第二位。问题是它们不是单独的矩阵,而是一个大矩阵的一部分。因此,我不能只说 m1*m2。

最后,我需要一个包含 15 个矩阵的平均矩阵 - 获得一个参与者的所有测量值 (n=15) 的平均值。例如,从示例数据中我会得到 ((m1+m2)/2):

          V1      V2      V3      V4      V5
[1,] 0.00000 0.48710 0.52205 0.57830 0.52120
[2,] 0.48710 0.00000 0.43005 0.56700 0.40305
[3,] 0.52205 0.43005 0.00000 0.57625 0.41490

【问题讨论】:

  • 欢迎。您能否以纯文本形式发布您的数据的一个小示例(即使用 3 列而不是 68 列) - 这样更容易提供帮助。谢谢。
  • 您的描述令人困惑。你需要mean还是sum
  • 我添加了更多信息,希望这可以澄清它。不确定我是否可以立即得到平均值,所以这就是我谈论 sum 的原因!
  • 按行表示?如果是,您想要的是 1:68、69:136 等行的平均值,它们都构成一个矩阵。然后对其他参与者重复此操作,等等?

标签: r for-loop matrix mean


【解决方案1】:

我不确定我是否正确理解了您要执行的操作,但我创建了一个向量,其中包含适当的索引,用于对矩阵的行进行子集化

number <- 1020

a <- (seq(1,number,68))
n <- as.numeric(length(a))
b <- vector()

for (i in (1:n)){
  b[i] <- a[i+1]-1}

b[n] <- number

c <- paste(a,b, sep = ":")

c

[1] "1:68"     "69:136"   "137:204"  "205:272"  "273:340" 
[6] "341:408"  "409:476"  "477:544"  "545:612"  "613:680" 
[11] "681:748"  "749:816"  "817:884"  "885:952"  "953:1020"

【讨论】:

  • 这已经有帮助了,我看看能不能找出子集! (也更新了我的问题,所以如果可以澄清它,欢迎提供任何额外的建议/提示)
【解决方案2】:

如果我正确理解了这个问题,以下函数可能会回答它。
该函数通过与参与者对应的子矩阵拆分输入矩阵,然后通过每个参与者内的子矩阵计算列均值。
返回值是平均值矩阵的列表。

funMean <- function(x, rows, matrices){
  f <- c(1, rep(0, rows*matrices - 1L))
  f <- rep(f, length.out = nrow(x))
  f <- cumsum(f)
  #
  g <- c(1, rep(0, rows - 1L))
  g <- rep(g, matrices)
  g <- cumsum(g)
  #
  x <- split(x, f)
  x <- lapply(x, matrix, ncol = rows)
  y <- lapply(x, \(X){
    z <- split(X, g)
    z <- lapply(z, matrix, ncol = rows)
    t(sapply(z, rowMeans, na.rm = TRUE))
  })
  y
}

使用假数据,而不是 68*68 有 Rows*RowsMats 而不是 15。

Rows <- 5
Mats <- 3

y <- funMean(Matrix_Alpha_ami, Rows, Mats)
y[[1]]
#        [,1]        [,2]         [,3]         [,4]        [,5]
#1 -0.9407742  0.40359467  0.233171598 -0.004998849  0.54604432
#2 -1.1864782 -0.58013231  0.004050014  0.102806769 -0.28126799
#3 -0.2209807  0.08324887 -0.417034539  0.695183587  0.02515484


do.call(rbind, y)

测试数据

set.seed(2021)
Matrix_Alpha_ami <- lapply(1:10, \(k){
  matrix(rnorm(Mats*Rows^2), ncol =  Rows)
})
Matrix_Alpha_ami <- do.call(rbind, Matrix_Alpha_ami)
dim(Matrix_Alpha_ami)

【讨论】:

    【解决方案3】:

    此解决方案使用一系列索引来构建一个 15 行矩阵以传递给colMeans。它应该运行得非常快。

    d <- 68L
    s <- 15L
    # traceable example matrix--replace m with your matrix
    m <- matrix(1:d, nrow = d*s*10, ncol = d)
    m <- m + (col(m) - 1)*d + ((row(m) - 1) %/% (d*s))*d^2
    
    # solution
    i1 <- seq(1L, by = d*s, length.out = nrow(m)/d/s) # top left index of the first d-by-d matrix for each individual
    i2 <- sequence(rep(d, length(i1)), i1) # indices of left-most column of the first d-by-d matrix for each individual
    i3 <- sequence(rep(d, length(i2)), i2, nrow(m)) # indices of the first d-by-d matrix for each individual
    i4 <- sequence(rep(s, length(i3)), i3, d) # indices for averaging (by sets of s)
    m2 <- matrix(colMeans(matrix(m[i4], nrow = s)), ncol = d, byrow = TRUE)
    

    【讨论】:

      猜你喜欢
      • 2012-11-11
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多