循环中cbind矩阵遇维度错误:summary结果长度不一致问题排查
解决summary()转换矩阵时的维度名称不匹配问题
我一眼就看到问题出在哪了——你的判断条件写反了,导致逻辑完全跑偏,直接触发了维度不匹配的错误!
先看你代码里的判断逻辑:
if(length(summary(foo[,i]==6))){ x <- as.matrix(c(summary(foo[,i]), 0)) rownames(x) <- c("Min.", "1st Qu.", "Median", "Mean", "3rd Qu.", "Max.", "NA's") }else if(length(summary(foo[,i]==7))){ x <- as.matrix(summary(foo[,i])) rownames(x) <- c("Min.", "1st Qu.", "Median", "Mean", "3rd Qu.", "Max.", "NA's") }
这里的致命错误是:你把==6/==7放进了summary()的括号里!summary(foo[,i]==6)实际上是对向量每个元素是否等于6的逻辑值做统计,这个结果的长度永远是6(逻辑向量的summary只会返回6个统计项),所以你的if条件永远为真——不管原向量有没有NA值,都会执行第一个分支。
举个具体场景:如果原向量有NA值,它的summary长度是7,这时候你执行c(summary(foo[,i]), 0)就会得到8个元素,转成矩阵后是8行1列,但你设置的rownames只有7个,这就直接触发了dimnames(x) <- dn : length of 'dimnames' [1] not equal to array extent的错误。
修正后的代码
把判断条件改对:先获取原向量的summary,再判断它的长度:
x <- matrix(NA, nrow=7, ncol=1) y <- NULL for(i in 1:ncol(foo)){ vec_summary <- summary(foo[,i]) # 先缓存当前向量的summary结果 if(length(vec_summary) == 6){ # 无NA值,summary长度为6 # 补充NA's对应的0,让总长度为7 vec_summary <- c(vec_summary, `NA's` = 0) } # 转成矩阵并设置标准行名 x <- as.matrix(vec_summary) rownames(x) <- c("Min.", "1st Qu.", "Median", "Mean", "3rd Qu.", "Max.", "NA's") y <- cbind(y, x) x <- matrix(NA, nrow=7, ncol=1) } # 给最终矩阵设置列名,对应原数据框的列 colnames(y) <- colnames(foo)
更简洁的优化方案
其实不用写for循环,用lapply批量处理更符合R的风格,也更不容易出错:
# 定义标准行名,确保顺序统一 standard_rows <- c("Min.", "1st Qu.", "Median", "Mean", "3rd Qu.", "Max.", "NA's") # 批量处理每一列 summary_list <- lapply(foo, function(vec){ s <- summary(vec) # 如果没有NA's项,补充0 if(!("NA's" %in% names(s))){ s <- c(s, `NA's` = 0) } # 按标准行名排序,保证顺序一致 s[standard_rows] }) # 把列表转成最终矩阵 y <- do.call(cbind, summary_list)
内容的提问来源于stack exchange,提问作者J.Q




