统计矩阵中行与列的类别值无序转换次数(含未出现转换)
统计矩阵/数据框中无序值转换的总次数(含未发生转换)
先看你给的示例矩阵,我们先把它创建出来看看结构:
mat <- matrix(c(2, 1, 2, 1, 3, 1, 2, 1, 2), nrow = 3) mat # [,1] [,2] [,3] # [1,] 2 1 2 # [2,] 1 3 1 # [3,] 2 1 2
你的需求很明确:要统计所有相邻元素(行方向左右、列方向上下)的无序转换次数,而且得把所有可能的元素组合都列出来——哪怕某个转换实际没发生,也要标记次数为0,最终输出成cat1 cat2 n的三列格式。
接下来我一步步给你实现:
步骤1:提取所有相邻元素对
我们需要把行内的左右相邻对、列内的上下相邻对都提取出来,然后合并到一起:
# 提取行向相邻对(每一行的第1-2个、第2-3个元素配对) row_pairs <- lapply(1:nrow(mat), function(i) cbind(mat[i, -ncol(mat)], mat[i, -1])) row_pairs <- do.call(rbind, row_pairs) # 提取列向相邻对(每一列的第1-2个、第2-3个元素配对) col_pairs <- lapply(1:ncol(mat), function(j) cbind(mat[-nrow(mat), j], mat[-1, j])) col_pairs <- do.call(rbind, col_pairs) # 合并行向和列向的所有相邻对 all_pairs <- rbind(row_pairs, col_pairs)
步骤2:把成对元素转为无序格式
因为是无序转换,比如1→2和2→1属于同一种转换,所以我们把每一对的两个元素按从小到大排序,统一格式:
# 对每一对元素排序,确保cat1 <= cat2 ordered_pairs <- t(apply(all_pairs, 1, sort))
步骤3:生成所有可能的元素组合
先找出矩阵里的所有唯一值,然后生成所有无序的两两组合(包括元素和自身配对的情况):
# 获取矩阵中所有唯一值并排序 unique_vals <- sort(unique(c(mat))) # 生成所有可能的无序组合(含自身配对) all_possible_pairs <- expand.grid(cat1 = unique_vals, cat2 = unique_vals) # 只保留cat1 <= cat2的无序组合,避免重复 all_possible_pairs <- all_possible_pairs[all_possible_pairs$cat1 <= all_possible_pairs$cat2, ]
步骤4:统计次数并补全未发生的转换
现在统计实际出现的无序对次数,再和所有可能组合合并,把没出现的转换次数设为0:
# 统计实际出现的无序对次数 pair_counts <- as.data.frame(table(ordered_pairs)) colnames(pair_counts) <- c("cat1", "cat2", "n") # 把因子类型转为整数,方便后续合并 pair_counts$cat1 <- as.integer(as.character(pair_counts$cat1)) pair_counts$cat2 <- as.integer(as.character(pair_counts$cat2)) # 合并到所有可能组合,缺失的次数填充为0 result <- merge(all_possible_pairs, pair_counts, by = c("cat1", "cat2"), all.x = TRUE) result$n[is.na(result$n)] <- 0 # 按cat1和cat2排序,和你期望的格式一致 result <- result[order(result$cat1, result$cat2), ] rownames(result) <- NULL
最后看一下结果,完全符合你的要求:
result # cat1 cat2 n # 1 1 1 0 # 2 1 2 8 # 3 1 3 4 # 4 2 2 0 # 5 2 3 0 # 6 3 3 0
顺便解释下你提到的1-3转换次数为4的原因:行方向里第二行有1↔3和3↔1各1次,列方向里第二列有1↔3和3↔1各1次,总共4次,排序后都归为1-3,所以次数是4。
内容的提问来源于stack exchange,提问作者Thomas White
相关产品推荐
相关产品推荐

