如何计算data.frame中实验行之间的成对共同克隆数量?
解决方案:计算实验对间的共同克隆数量
方法一:适合小数据集(直观易懂)
先将每个实验的克隆提取为列表,再生成所有实验对并计算交集大小:
# 构建示例数据集 df <- data.frame( Exp_No = c("Exp1", "Exp2", "Exp3", "Exp4", "Exp5", "Exp6"), Clone1 = c("Egxn2", "Egxn4", "Egxn2", "Egxn6", "Egxn2", "Egxn4"), Clone2 = c("Egxn11", "Egxn13", "Egxn6", "Egxn14", "Egxn11", "Egxn2"), Clone3 = c("Egxn6", "Egxn16", "Egxn11", "Egxn4", "Egxn6", "Egxn5"), Clone4 = c("Egxn13", "Egxn6", "Egxn18", "Egxn18", "Egxn13", "Egxn18"), stringsAsFactors = FALSE ) # 提取每个实验的克隆列表 clones_list <- lapply(1:nrow(df), function(i) unlist(df[i, -1])) names(clones_list) <- df$Exp_No # 生成所有不重复实验对 exp_pairs <- combn(names(clones_list), 2, simplify = FALSE) # 计算每对的共同克隆数 common_counts <- sapply(exp_pairs, function(pair) { length(intersect(clones_list[[pair[1]]], clones_list[[pair[2]]])) }) # 整理成目标格式 result <- data.frame( Exp_A = sapply(exp_pairs, `[`, 1), Exp_B = sapply(exp_pairs, `[`, 2), Common_Count = common_counts, stringsAsFactors = FALSE ) print(result)
输出结果与期望格式一致,示例片段:
Exp_A Exp_B Common_Count 1 Exp1 Exp2 2 2 Exp1 Exp3 3 3 Exp1 Exp4 1 4 Exp1 Exp5 4 5 Exp1 Exp6 1 6 Exp2 Exp3 1 ...
方法二:适合大数据集(9000行+,高效省内存)
针对大规模数据,推荐用克隆-实验二进制矩阵乘法的方法,底层优化的矩阵运算比循环/列表操作快得多,还能通过稀疏矩阵节省内存:
常规矩阵版本
library(tidyr) library(dplyr) # 将宽格式数据转成长格式,去重(避免同一克隆在实验中重复计数) long_df <- df %>% pivot_longer(cols = -Exp_No, names_to = "temp", values_to = "Clone") %>% select(Exp_No, Clone) %>% distinct() # 构建克隆-实验的0-1矩阵(克隆在行,实验在列) clone_matrix <- table(long_df$Clone, long_df$Exp_No) clone_matrix[clone_matrix > 1] <- 1 # 矩阵乘法直接得到实验对的共同克隆数矩阵 common_matrix <- t(clone_matrix) %*% clone_matrix # 转成目标长格式(只保留不重复的实验对) result_long <- as.data.frame(as.table(common_matrix)) %>% filter(Var1 < Var2) %>% rename(Exp_A = Var1, Exp_B = Var2, Common_Count = Freq) %>% arrange(Exp_A, Exp_B) print(result_long)
稀疏矩阵版本(内存友好)
如果克隆数量极大,用稀疏矩阵进一步降低内存占用:
library(Matrix) library(tidyr) library(dplyr) # 转长格式并去重 long_df <- df %>% pivot_longer(cols = -Exp_No, names_to = "temp", values_to = "Clone") %>% select(Exp_No, Clone) %>% distinct() # 构建稀疏0-1矩阵 sparse_clone_matrix <- sparseMatrix( i = as.integer(factor(long_df$Clone)), j = as.integer(factor(long_df$Exp_No)), x = 1, dimnames = list(levels(factor(long_df$Clone)), levels(factor(long_df$Exp_No))) ) # 稀疏矩阵乘法计算共同克隆数 sparse_common_matrix <- t(sparse_clone_matrix) %*% sparse_clone_matrix # 转成目标格式 result_sparse <- as.data.frame(as.table(sparse_common_matrix)) %>% filter(Var1 < Var2) %>% rename(Exp_A = Var1, Exp_B = Var2, Common_Count = Freq) %>% arrange(Exp_A, Exp_B) print(result_sparse)
内容的提问来源于stack exchange,提问作者Ilaria
相关产品推荐
相关产品推荐

