R中使用带if条件的for循环按原表列值填充新表问题
问题原因及解决方案
错误根因
你的代码存在两处核心问题:
- 第三个判断分支的引用对象错误:判断
GG取值时用了geno_no_miss$V5[i],而非当前处理的test$col2[i],导致GG的匹配逻辑完全失效,所有非AA、非CC的行都会进入最后的else分支。 - 循环中每次生成的临时data.frame没有指定统一列名,R会自动按第一行的列名做匹配,导致后续行的数值位置错位,最终出现所有0.91都在第一列的问题。
修正后的循环实现
test2 <- data.frame() # 提前指定统一列名,避免匹配错位 col_names <- c("colA", "colC", "colG", "colT") for(i in 1:nrow(test)) { if(test$col2[i] == "AA"){ row_df <- data.frame(0.91, 0.03, 0.03, 0.03) } else if (test$col2[i] == "CC"){ row_df <- data.frame(0.03, 0.91, 0.03, 0.03) } else if (test$col2[i] == "GG"){ row_df <- data.frame(0.03, 0.03, 0.91, 0.03) } else if (test$col2[i] == "TT"){ row_df <- data.frame(0.03, 0.03, 0.03, 0.91) } colnames(row_df) <- col_names test2 <- rbind(test2, row_df) }
更高效的向量化实现(推荐)
不用循环,直接先生成全为0.03的矩阵,再根据col2的取值修改对应位置的数值即可,性能远高于循环rbind:
# 生成初始全0.03的矩阵 test2 <- matrix(0.03, nrow = nrow(test), ncol = 4, dimnames = list(NULL, c("colA", "colC", "colG", "colT"))) # 建立碱基和列索引的映射 col_map <- c("AA" = 1, "CC" = 2, "GG" = 3, "TT" = 4) # 对应位置赋值为0.91 test2[cbind(1:nrow(test), col_map[test$col2])] <- 0.91 # 转为data.frame(可选) test2 <- as.data.frame(test2)
运行后输出的test2完全符合预期:
| colA | colC | colG | colT |
|---|---|---|---|
| 0.91 | 0.03 | 0.03 | 0.03 |
| 0.03 | 0.91 | 0.03 | 0.03 |
| 0.03 | 0.03 | 0.91 | 0.03 |
| 0.03 | 0.03 | 0.03 | 0.91 |
| 0.03 | 0.03 | 0.91 | 0.03 |
内容的提问来源于stack exchange,提问作者Eric González
相关产品推荐
相关产品推荐

