R语言中按流行度从低到高实现无冲突主题分配的最简算法
带已分配追踪的主题无重复分配实现
原逻辑的核心缺陷
原有直接按max.col逐行填值的方式,没有跟踪已经完成分配的列(即待匹配的id对象),会出现同一id被多个主题重复匹配的问题,无法满足「每个id仅对应一个主题、低流行度主题优先抢占最优匹配位置」的要求。
实现思路
依托已经按流行度升序排好的数据集,逐行处理每个主题的匹配过程:
- 初始化和数据集维度匹配的空结果矩阵,同时维护一个记录已占用列的向量
- 对每个主题,先定位该行中所有最高偏好等级(即值为3)的列位置
- 过滤掉已经被之前主题占用的列,取第一个可用位置填入当前主题名称
- 将该位置标记为已占用,继续处理下一个主题
完整代码实现
首先复现测试数据集:
library(tidyverse) data <- data.frame(topic = c("A", "B", "C", "D", "E"), id1 = c(1,2,3,1,2), id2 = c(3,3,2,1,3), id3 = c(1,1,3,3,2), id4 = c(3,1,2,2,1), id5 = c(2,2,1,3,1), id6 = c(3,1,1,1,3)) %>% mutate(popularity = rowSums(. == 3)) %>% arrange(popularity)
然后是带占用追踪的匹配逻辑:
# 初始化结果矩阵:行数对应主题数,列数对应id总数 my_matrix <- matrix(NA, nrow = nrow(data), ncol = sum(grepl("^id", names(data)))) # 记录已经被分配的列位置 occupied_cols <- c() # 按流行度从低到高逐行处理 for (row_idx in seq_len(nrow(data))) { # 提取当前主题对应的各id偏好值 current_pref <- as.numeric(data[row_idx, grepl("^id", names(data))]) # 筛选符合要求的位置:偏好值为最高等级、列未被占用 valid_pos <- which(current_pref == 3 & !(seq_along(current_pref) %in% occupied_cols)) # 取第一个可用位置完成分配 assign_pos <- valid_pos[1] my_matrix[row_idx, assign_pos] <- data$topic[row_idx] # 标记该列已被占用 occupied_cols <- c(occupied_cols, assign_pos) }
运行结果
my_matrix # [,1] [,2] [,3] [,4] [,5] [,6] # [1,] NA "B" NA NA NA NA # [2,] "C" NA NA NA NA NA # [3,] NA NA "D" NA NA NA # [4,] NA NA NA NA NA "E" # [5,] NA NA NA "A" NA NA
逐行匹配过程拆解:
- 最低流行度的主题B,最高偏好位置为第2列(id2),该位置未被占用,完成分配,标记第2列已占
- 主题C的最高偏好位置为第1列(id1)、第3列(id3),第1列未被占用,完成分配,标记第1列已占
- 主题D的最高偏好位置为第3列(id3)、第5列(id5),第3列未被占用,完成分配,标记第3列已占
- 主题E的最高偏好位置为第2列(已被B占用)、第6列(id6),跳过已占用位置,在第6列完成分配,标记第6列已占
- 最高流行度的主题A的最高偏好位置为第2列(已占)、第4列(id4)、第6列(已占),跳过两个已占用列,在第4列完成分配
内容的提问来源于stack exchange,提问作者Marco
相关产品推荐
相关产品推荐

