R语言data.table筛选后列正常但无数据行的问题排查
问题描述
正在对data.table tab_cond_Loc_phases中的实验条件执行t.test分析:
- 数据集包含82个实验条件,通过
combn生成约3300个无重复对比对,t.test执行正常,结果存储在ttest_compList_2中。 - 为结果表添加额外列后,尝试筛选
p_value < 0.05的行时,新生成的ttest_compList表结构正常但无数据行,且无报错信息。 - 若用
select替代filter,会触发如下错误:
Error in `select()`: ! Problem while evaluating `p_value < 0.05`. Caused by error: ! object 'p_value' not found
该问题仅在条件数量较多的数据集上出现,目前无法定位代码无法识别p_value列的原因,同时寻求t.test实现方式的优化建议。
最小可复现代码(MRE)
controls <- c("WT+DMSO", "MUT+DMSO") # 获取列中唯一的条件名称 condition_vec <- unique(tab_cond_Loc_phases$condition) # 生成所有无重复的条件组合 col_vec <- combn(condition_vec, 2, FUN = paste) # 存储t.test结果的列表 con_tab_2 <- list() for (comparison in 1:ncol(col_vec)) { # 循环遍历组合,执行t.test tmp_ttest_2 <- t.test(tab_cond_Loc_phases[condition == col_vec[1, comparison], exp_sums], tab_cond_Loc_phases[condition == col_vec[2, comparison], exp_sums]) # 构造存储单条t.test结果的data.table res_tab_2 <- data.table( condition1 = combn(condition_vec, 2)[1, comparison], condition2 = combn(condition_vec, 2)[2, comparison], t_statistic = tmp_ttest_2$statistic, df = tmp_ttest_2$parameter, p_value = tmp_ttest_2$p.value, mean_cond1 = tmp_ttest_2$estimate[1], mean_cond2 = tmp_ttest_2$estimate[2], method = tmp_ttest_2$method ) # 将当前结果加入列表 con_tab_2[[comparison]] <- rbind(res_tab_2) print(paste('t.test comparison group ', comparison, '/', ncol(col_vec))) } # 合并所有结果为一个data.table ttest_compList_2 <- rbindlist(con_tab_2) # 筛选包含至少一个对照组且p值显著的结果 ttest_compList <- ttest_compList_2 %>% mutate(pair = as.numeric(factor(1:nrow(ttest_compList_2))), xmin = pair - 0.2, xmax = pair + 0.2) %>% dplyr::filter(p_value < 0.05, grepl(paste(controls, collapse = "|"), condition1) | grepl(paste(controls, collapse = "|"), condition2))
更新:优化后的t.test实现
基于建议改进了t.test执行逻辑,原方法耗时约33秒,新方法仅需约12秒:
library(tidyverse) library(data.table) controls <- c("WT+DMSO", "MUT+DMSO") # 获取列中唯一的条件名称 condition_vec <- unique(tab_cond_Loc_phases$condition) # 创建空data.table存储结果 ttest_results <- data.table() # 统计每个条件的重复次数,避免单重复条件报错 occurances <- tab_cond_Loc_phases[, list(replicates = .N), by = condition] # 仅当所有条件重复次数>1时执行t.test if(min(occurances[['replicates']]) > 1) { # 生成所有无重复的条件组合(列表形式) col_vec <- combn(condition_vec, 2, simplify = FALSE) col_vec_length <- length(col_vec) for (i in 1:col_vec_length) { # 提取当前对比的两个条件 condition1 <- col_vec[[i]][1] condition2 <- col_vec[[i]][2] # 筛选对应条件的数据子集 conds_subset1 <- tab_cond_Loc_phases[condition == condition1, exp_sums] conds_subset2 <- tab_cond_Loc_phases[condition == condition2, exp_sums] # 执行t.test ttest <- t.test(conds_subset1, conds_subset2) # 将结果追加到data.table中 ttest_results <- rbind(ttest_results, data.table(condition1 = condition1, condition2 = condition2, mean_condition1 = ttest$estimate[1], mean_condition2 = ttest$estimate[2], statistic = ttest$statistic, df = ttest$parameter, p.value = ttest$p.value, method = ttest$method)) } } # 筛选包含至少一个对照组且p值显著的结果 ttest_results <- ttest_results %>% mutate(pair = as.numeric(factor(1:nrow(ttest_results))), xmin = pair - 0.2, xmax = pair + 0.2) %>% filter(p.value < 0.05, condition1 %in% controls | condition2 %in% controls)
内容的提问来源于stack exchange,提问作者Chris
相关产品推荐
相关产品推荐

