按行针对多subtype组用IQR去除deg矩阵异常值遇空行问题
问题描述
我有一个矩阵deg,需要将其列名与数据框clin.info的行名匹配,clin.info包含subtype列。我希望按每个subtype分组,对deg的每行数据用四分位距(IQR)去除异常值,但运行下方代码后没有返回任何行:
for (rows in 1:nrow(deg)){ Q <- quantile(rows, probs=c(.25, .75), na.rm = FALSE) iqr <- IQR(rows) up <- Q[2]+1.5*iqr # Upper Range low<- Q[1]-1.5*iqr # Lower Range eliminated<- subset(deg, rows > (Q[1] - 1.5*iqr) & rows < (Q[2]+1.5*iqr)) }
输入数据
# clin.info 前5行 > dput(clin.info[,c("survival", "subtype")][1:5,]) structure(list(survival = c("lts", "lts", "lts", "lts", "lts" ), subtype = c("2a", "1a", "2a", "1a", "1a")), row.names = c("TCGA.Y8.A8S1.01", "TCGA.Y8.A8S0.01", "TCGA.Y8.A8RZ.01", "TCGA.Y8.A8RY.01", "TCGA.Y8.A897.01" ), class = "data.frame") # deg 前5行5列 > dput(deg[1:5,1:5]) structure(c(493, 2498, 387, 1154.93, 362, 43800000, 152900000000, 60300000000, 194400000.56, 5940000, 1270, 3300, 735, 2120.99, 971, 201, 1921, 227, 1246.66, 411, 717, 2655, 624, 2049.36, 551), dim = c(5L, 5L), dimnames = list( c("ADAMTS13", "MST1", "TUBE1", "RPAIN", "NPHP1"), c("TCGA.2K.A9WE.01", "TCGA.2Z.A9J1.01", "TCGA.2Z.A9J3.01", "TCGA.2Z.A9J5.01", "TCGA.2Z.A9J6.01")))
预期输出
structure(c(493, 10000, 387, 1154.93, 1270, 3300, 735, 2120.99, 971, 201, 1921, 227, 1246.66, 411, 717, 2655, 624, 2049.36, 551), dim = c(5L, 5L), dimnames = list( c("ADAMTS13", "MST1", "TUBE1", "RPAIN", "NPHP1"), c("TCGA.Y8.A8S1.01", "TCGA.Y8.A8RZ.01", "TCGA.Y8.A8RY.01", "TCGA.Y8.A897.01")))
问题分析
原代码存在3个核心错误:
- 循环变量使用错误:
rows是行号(1、2、3...),不是deg的行数据,quantile(rows)计算的是行号的分位数,完全偏离需求; - 未按subtype分组处理:完全没有利用
clin.info的分组信息,没有实现“每个subtype组内去异常值”的逻辑; - subset条件错误:用行号
rows作为判断条件,而非该行的实际数据值,导致过滤逻辑完全失效。
解决方案
步骤1:对齐样本
先确保deg的列名和clin.info的行名匹配,取两者的交集样本:
# 获取共同样本名 common_samples <- intersect(colnames(deg), rownames(clin.info)) # 过滤矩阵和数据框 deg_filtered <- deg[, common_samples] clin_filtered <- clin.info[common_samples, ]
步骤2:按subtype分组,每行去除异常值
定义一个函数,对每行数据按subtype分组计算IQR范围,过滤掉异常值(或标记为NA),再重组结果:
# 定义按组去除异常值的函数 remove_outliers_by_group <- function(row_data, groups) { # 按分组拆分数据 grouped_data <- split(row_data, groups) # 对每个分组处理 cleaned_data <- lapply(grouped_data, function(x) { q <- quantile(x, probs = c(0.25, 0.75), na.rm = TRUE) iqr_val <- IQR(x, na.rm = TRUE) lower <- q[1] - 1.5 * iqr_val upper <- q[2] + 1.5 * iqr_val # 保留非异常值,异常值设为NA(也可以直接删除,根据需求调整) x[x < lower | x > upper] <- NA return(x) }) # 合并回原顺序 unsplit(cleaned_data, groups) } # 对deg_filtered的每行应用函数 deg_cleaned <- t(apply(deg_filtered, 1, remove_outliers_by_group, groups = clin_filtered$subtype)) # 如果需要删除包含NA的行(根据需求选择) # deg_cleaned <- deg_cleaned[complete.cases(deg_cleaned), ]
说明
- 上述代码会将每个subtype组内的异常值标记为
NA,如果需要直接删除异常值对应的样本,可调整函数内的逻辑; - 若你的需求是“保留非异常值的行”(即该行在所有分组中都没有异常值),可在最后用
complete.cases()过滤; - 预期输出中样本名和输入的
deg样本不匹配,需确保你的原始数据中deg的列名确实包含clin.info的行名,否则common_samples会为空,需检查数据匹配情况。
内容的提问来源于stack exchange,提问作者Anon
相关产品推荐
相关产品推荐

