大数据框按每8列分组计算行均值的循环问题求助
问题描述
我有一个大数据框,每个样本对应8列,共200个样本,需要按每8列一组计算行均值(比如第1-8列、9-16列这类分组),行名为基因名。尝试了以下嵌套循环代码,但无法正常运行:
for(j in 1:nrow(mat)){ for (i in 1:ncol(mat)/8) { row_m[j, i]<- rowMeans(mat[j,c(i:i+7)]) } }
示例数据:
dput(head(deconv3[1:9], 20)) structure(list(AM.amplifying.intestine = c(0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0), AM43.5.epithelial.of.mammary = c(0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 4.76506, 0, 0, 1406.48, 0, 196.401, 0, 1996.5, 0), AM.epithelium.of.bronchus = c(549.649, 1647.63, 0, 0, 0, 0, 0, 0, 699.868, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0), AM.epithelium.of.intestine = c(0, 0, 0, 0, 0, 0, 572.85, 59.2414, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0), AM.epithelium.of.trachea = c(0, 0, 0, 0, 199.549, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0), AM.kidney.epithelial.cell = c(0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1.32926, 0, 0, 333.592, 0), AM.medullary.thymic.epithelial.cell = c(126.847, 0, 0, 0, 0, 0, 0, 0, 0, 63.1822, 0, 0, 0, 0, 0, 0, 0, 26.0598, 0, 11.117), AM.myoepithelial.cell = c(0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0), AK.amplifying.intestine = c(0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0)), row.names = c("A1BG", "A2M", "NAT2", "SERPINA3", "AANAT", "ABAT", "ABCA2", "ABCA3", "ABCB7", "ABCA4", "ABO", "ACACA", "ACADL", "ACADS", "ACADSB", "ACAT1", "ACLY", "ACR", "ACP1", "ACRV1"), class = "data.frame")
原代码的问题
- 循环变量生成错误:
1:ncol(mat)/8会先生成1到列数的序列再除以8,得到的是小数,不是每组的起始索引 - 列索引写法错误:
i:i+7会被解析成(i:i)+7,正确的连续索引写法应该是i:(i+7) - 结果矩阵未初始化:直接给
row_m[j,i]赋值会报错,因为row_m还没创建
解决方案
方法1:向量化分组计算(推荐,效率更高)
利用split.default按列分组,再对每组计算行均值,最后合并结果:
# 生成分组索引:每8列一组 groups <- rep(1:(ncol(mat)%/%8), each=8) # 处理列数不是8整数倍的剩余列(可选,根据需求调整) if(ncol(mat) %%8 != 0){ groups <- c(groups, rep(max(groups)+1, ncol(mat)%%8)) } # 按分组计算行均值 row_m <- sapply(split.default(mat, groups), rowMeans) # 给结果列命名(可选) colnames(row_m) <- paste0("Sample_", 1:ncol(row_m))
方法2:修正循环代码
如果坚持用循环,先初始化结果矩阵,再修正循环逻辑:
# 计算分组数量 n_groups <- ncol(mat) %/%8 # 初始化结果矩阵,行名和原数据一致 row_m <- matrix(NA, nrow = nrow(mat), ncol = n_groups, dimnames = list(rownames(mat), paste0("Sample_",1:n_groups))) # 循环计算每个分组的行均值 for(i in 1:n_groups){ # 计算当前分组的列索引范围 col_indices <- (i-1)*8 + 1 : (i*8) row_m[,i] <- rowMeans(mat[, col_indices]) }
示例测试
用你提供的9列示例数据测试,前8列为一组,第9列为一组:
# 加载示例数据 mat <- structure(list(AM.amplifying.intestine = c(0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0), AM43.5.epithelial.of.mammary = c(0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 4.76506, 0, 0, 1406.48, 0, 196.401, 0, 1996.5, 0), AM.epithelium.of.bronchus = c(549.649, 1647.63, 0, 0, 0, 0, 0, 0, 699.868, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0), AM.epithelium.of.intestine = c(0, 0, 0, 0, 0, 0, 572.85, 59.2414, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0), AM.epithelium.of.trachea = c(0, 0, 0, 0, 199.549, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0), AM.kidney.epithelial.cell = c(0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1.32926, 0, 0, 333.592, 0), AM.medullary.thymic.epithelial.cell = c(126.847, 0, 0, 0, 0, 0, 0, 0, 0, 63.1822, 0, 0, 0, 0, 0, 0, 0, 26.0598, 0, 11.117), AM.myoepithelial.cell = c(0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0), AK.amplifying.intestine = c(0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0)), row.names = c("A1BG", "A2M", "NAT2", "SERPINA3", "AANAT", "ABAT", "ABCA2", "ABCA3", "ABCB7", "ABCA4", "ABO", "ACACA", "ACADL", "ACADS", "ACADSB", "ACAT1", "ACLY", "ACR", "ACP1", "ACRV1"), class = "data.frame") # 用方法1计算 groups <- rep(1:(ncol(mat)%/%8), each=8) if(ncol(mat) %%8 !=0){ groups <- c(groups, rep(max(groups)+1, ncol(mat)%%8)) } row_m <- sapply(split.default(mat, groups), rowMeans) colnames(row_m) <- paste0("Sample_", 1:ncol(row_m)) # 查看前6行结果 head(row_m)
输出示例:
Sample_1 Sample_2 A1BG 84.5620 0 A2M 205.9538 0 NAT2 0.0000 0 SERPINA3 0.0000 0 AANAT 24.9436 0 ABAT 0.0000 0
内容的提问来源于stack exchange,提问作者Vahid
相关产品推荐
相关产品推荐

