如何对100×100矩阵按10×10块计算对角线与非对角线均值?
分块计算矩阵对角线与三角区域均值
我有一个100行100列的矩阵,需要按每10行10列的块(例如1-10行1-10列、11-20行11-20列等),分别计算每个块内对角线元素的均值,以及上下三角非对角线元素的均值,最终得到一个10×10的结果矩阵。尝试了一段代码但未得到预期结果,求简洁实现方法。
示例矩阵生成代码
a <- runif(100, 0.0, 1.0) b <- matrix(a, 10, 10) dput(b[1:5,1:5]) structure(c(0.84062766819261, 0.147046645870432, 0.400851072976366, 0.413125045597553, 0.983001669868827, 0.875247176503763, 0.780131382867694, 0.135052096098661, 0.697219847934321, 0.124223494203761, 0.341172023210675, 0.0648272060789168, 0.495929004857317, 0.560068692779168, 0.427216225070879, 0.322575035970658, 0.380825364030898, 0.268939214758575, 0.308511241106316, 0.583480153232813, 0.220581432571635, 0.440520159434527, 0.281114168930799, 0.192230961984023, 0.468790194252506), dim = c(5L, 5L))
尝试的代码
group_number <- rep(1:(nrow(d_num)/10), each=10) Mean_vals <- aggregate(d_num, by=list(group_number), mean)
解决方案
方法1:嵌套循环实现(直观易懂)
先定义块大小,遍历每个块并分别计算三类均值,最终得到三个10×10的结果矩阵:
# 生成100×100的测试矩阵(替换为你的实际矩阵) set.seed(123) mat <- matrix(runif(10000), nrow=100, ncol=100) block_size <- 10 n_blocks <- nrow(mat) / block_size # 初始化三个结果矩阵 diag_mean <- matrix(NA, n_blocks, n_blocks) upper_mean <- matrix(NA, n_blocks, n_blocks) lower_mean <- matrix(NA, n_blocks, n_blocks) # 遍历所有块 for (i in 1:n_blocks) { row_range <- ((i-1)*block_size + 1):(i*block_size) for (j in 1:n_blocks) { col_range <- ((j-1)*block_size + 1):(j*block_size) current_block <- mat[row_range, col_range] # 对角线元素均值 diag_mean[i,j] <- mean(diag(current_block)) # 上三角非对角线元素均值 upper_mean[i,j] <- mean(current_block[upper.tri(current_block, diag=FALSE)]) # 下三角非对角线元素均值 lower_mean[i,j] <- mean(current_block[lower.tri(current_block, diag=FALSE)]) } } # 查看第一块的对角线均值 diag_mean[1,1] # 查看第一块的上三角均值 upper_mean[1,1]
方法2:数据框分组实现(无需循环)
通过将矩阵转换为数据框,添加分组和块内位置信息,用tapply批量计算均值:
# 生成测试矩阵 set.seed(123) mat <- matrix(runif(10000), nrow=100, ncol=100) block_size <- 10 n_blocks <- nrow(mat) / block_size # 构建包含分组和块内位置的数据框 row_groups <- rep(1:n_blocks, each=block_size) col_groups <- rep(1:n_blocks, each=block_size) df <- data.frame( row_grp = row_groups, col_grp = rep(col_groups, each=nrow(mat)), value = as.vector(mat), block_row = rep(1:block_size, nrow(mat)), block_col = rep(rep(1:block_size, each=block_size), n_blocks) ) # 计算对角线均值 diag_mean <- tapply(df$value[df$block_row == df$block_col], list(df$row_grp[df$block_row == df$block_col], df$col_grp[df$block_row == df$block_col]), mean) # 计算上三角非对角线均值 upper_mean <- tapply(df$value[df$block_row < df$block_col], list(df$row_grp[df$block_row < df$block_col], df$col_grp[df$block_row < df$block_col]), mean) # 计算下三角非对角线均值 lower_mean <- tapply(df$value[df$block_row > df$block_col], list(df$row_grp[df$block_row > df$block_col], df$col_grp[df$block_row > df$block_col]), mean)
合并结果(可选)
如果需要将三个均值整合到一个结构中,可以使用三维数组:
result_array <- array(c(diag_mean, upper_mean, lower_mean), dim=c(n_blocks, n_blocks, 3)) dimnames(result_array) <- list( paste0("Block_", 1:n_blocks), paste0("Block_", 1:n_blocks), c("Diag_Mean", "Upper_Mean", "Lower_Mean") ) # 查看第1行第1列块的三个均值 result_array[1,1,]
原代码问题说明
你之前的代码仅按行分组计算了整行的均值,既没有实现10×10的分块逻辑,也没有区分对角线、上三角、下三角区域,因此无法得到预期结果。
内容的提问来源于stack exchange,提问作者Gopi
相关产品推荐
相关产品推荐

