如何提取布尔矩阵中每行值为TRUE的列名并整理结果?
提取布尔矩阵每行TRUE对应的列名
我正在处理一个由基因表达值筛选(大于0.5)得到的布尔矩阵,矩阵元素仅为TRUE/FALSE。需要为每行提取值为TRUE的列名,最终希望得到以行号为列标题、对应TRUE列名为内容的表格,或者仅得到按行号分组的列名列表。我尝试使用for循环,但无法获取列名,恳请帮助!
输入示例
> sc_mydata > 0.5 Slc6a14 / 1420504_at Calca / 1452004_at Ms4a4d / 1418990_at Hsd17b14 / 1429802_at 1432227_at [1,] FALSE FALSE FALSE TRUE TRUE [2,] FALSE TRUE FALSE FALSE TRUE [3,] FALSE FALSE FALSE FALSE FALSE [4,] TRUE FALSE TRUE FALSE FALSE
解决方案
方法1:基础R apply 函数(最直接)
先把布尔矩阵赋值给变量,再逐行提取对应TRUE的列名:
# 保存布尔矩阵 bool_mat <- sc_mydata > 0.5 # 逐行提取TRUE对应的列名,返回列表 result_list <- apply(bool_mat, 1, function(row) { colnames(bool_mat)[row] }) # 查看结果 result_list
输出结果:
[[1]] [1] "Hsd17b14 / 1429802_at" "1432227_at" [[2]] [1] "Calca / 1452004_at" "1432227_at" [[3]] character(0) [[4]] [1] "Slc6a14 / 1420504_at" "Ms4a4d / 1418990_at"
如果需要表格形式(行号为列,列名用逗号分隔):
# 列表转数据框,空行显示为空字符串 result_df <- data.frame( 行号 = seq_along(result_list), TRUE列名 = sapply(result_list, function(x) if(length(x) == 0) "" else paste(x, collapse = ", ")) ) # 查看表格 result_df
输出:
行号 TRUE列名 1 1 Hsd17b14 / 1429802_at, 1432227_at 2 2 Calca / 1452004_at, 1432227_at 3 3 4 4 Slc6a14 / 1420504_at, Ms4a4d / 1418990_at
方法2:for循环实现(修正版)
如果坚持用for循环,关键是正确索引列名:
result_list <- vector("list", nrow(bool_mat)) for(i in 1:nrow(bool_mat)) { # 提取第i行中为TRUE的列名 result_list[[i]] <- colnames(bool_mat)[bool_mat[i, ]] }
运行后得到和apply方法一致的列表结果。
方法3:tidyverse 语法(适合熟悉该框架的用户)
用dplyr和tidyr转换为表格:
library(dplyr) library(tidyr) library(tibble) bool_mat %>% as_tibble(rownames = "行号") %>% pivot_longer(-行号, names_to = "列名", values_to = "是否TRUE") %>% filter(是否TRUE) %>% group_by(行号) %>% summarise(TRUE列名 = paste(列名, collapse = ", "), .groups = "drop") %>% right_join(tibble(行号 = as.character(seq(nrow(bool_mat)))), by = "行号") %>% mutate(TRUE列名 = replace_na(TRUE列名, ""))
输出同样是包含所有行号的表格,空行对应内容为空字符串。
内容的提问来源于stack exchange,提问作者mbeavitt
相关产品推荐
相关产品推荐

