含重复值(ties)的变量三等分最优阈值求解:避免重复值跨组
带重复值的数值变量均衡三分组方案
问题背景
现有连续数值变量x,需要将其划分为三组观测数尽可能均衡的分组,要求:
- 各组观测数的最大值与最小值差值最小
- 重复值不能跨组(同一数值必须全部分配到同一组)
- 传统分位数(quantile)方法因存在重复值,无法得到最优分组(分位数阈值会导致重复值被强行拆分到不同组)
解决方案:遍历最优阈值法
核心思路:利用变量的唯一值作为候选阈值,遍历所有可能的阈值组合,计算每组的观测数,筛选出组大小差异最小的组合。
实现步骤
- 获取变量
x的唯一值并排序,得到候选阈值集合 - 生成所有可能的两个阈值组合(确保第一个阈值 < 第二个阈值)
- 对每个组合,计算三组的观测数:
<=阈值1、>阈值1且<=阈值2、>阈值2 - 计算每组大小的最大值与最小值的差值,选择差值最小的阈值组合
- 若存在多个最优组合,可任选其一(或根据需求选择更偏向某组的)
R语言代码实现
# 定义目标变量x(用户提供的数据) x = c(26, 34, 27, 26, 38, 40, 34, 28, 27, 36, 29, 30, 29, 44, 30, 34, 32, 30, 26, 29, 34, 32, 38, 27, 35, 29, 28, 34, 26, 27, 27, 30, 27, 28, 27, 28, 28, 27, 29, 29, 28, 29, 29, 28, 29, 29, 28, 27, 29, 27, 36, 34, 34, 39, 34, 31, 31, 33, 35, 31, 31, 32, 37, 38, 32, 31, 28, 33, 33, 28, 27, 27, 30, 31, 32, 28, 27, 31, 36, 27, 33, 31, 34, 31, 35, 38, 37, 36, 39, 33, 33, 28, 41, 34, 35, 37, 37, 41, 32, 37, 30, 34, 38, 30, 40, 35, 31, 30, 30, 29, 29, 30, 29, 35, 28, 27, 27, 27, 29, 27, 28, 27, 27, 27, 26, 28, 28, 27, 29, 29, 27, 27, 27, 27, 29, 27, 28, 27, 28, 34, 29, 28, 28, 28, 29, 38, 33, 39, 28, 27, 28, 27, 29, 34, 29, 32, 70, 26, 29, 43, 48, 30, 30, 27, 26, 29, 27, 27, 27, 27, 28, 28, 27, 28, 28, 27, 28, 28, 38, 52, 26, 31, 56, 29, 29, 36, 28, 35, 32, 34, 35, 28, 27, 37, 26, 26, 32, 26, 27, 30, 28, 28, 30, 29, 30, 29, 29, 28, 26, 33, 39, 26, 31, 27, 28, 30, 30, 28, 28, 29, 26, 27, 26, 29, 28, 28, 27, 27, 27, 28, 27, 28, 28, 28, 28, 28, 27, 27, 29, 27, 26, 28, 28, 27, 27, 28, 27, 28, 28, 30, 27, 30, 28, 32, 34, 28, 27, 28, 28, 27, 28, 27, 27, 27, 28, 27, 28, 27, 27, 28, 27, 27, 27, 27, 27, 28, 27, 27, 27, 26, 27, 27, 30, 28, 27, 30, 30, 42, 26, 27, 40, 33, 29, 29, 29, 52, 58, 44, 32, 43, 30, 27, 38, 30, 27, 30, 27, 31, 39, 35, 32, 32, 34, 45, 31, 44, 42, 29, 29, 30, 30, 50, 30, 33, 31, 35, 27, 28, 27, 28, 55, 28, 28, 28, 27, 27, 28, 29, 27, 28, 27, 28, 28, 28, 28, 27, 28, 29, 34, 45, 27, 29, 61, 38, 62, 29, 36, 36, 30, 31, 45, 27, 30, 28, 29, 44, 45, 42, 52, 50, 52, 42, 38, 42, 32, 27, 37, 40, 52, 27, 36, 38, 39, 34, 30, 29, 34, 29, 26, 35, 43, 33, 40, 35, 33, 41, 61, 45, 35, 52, 50, 38, 43, 29, 35, 38, 39, 31, 28, 28, 29, 34, 27, 30, 32, 28, 26, 28, 27, 26, 29, 27, 26, 29, 29, 27, 29, 27, 27, 29, 27, 30, 29, 25, 30, 27, 29, 29, 30, 30, 27, 30, 28, 28, 27, 29, 29, 30, 29, 27, 28, 28, 28, 29, 28, 28, 27, 28, 29, 28, 29, 27, 28, 28, 28, 30, 27, 27, 28, 26, 28, 27, 27, 28, 28, 28, 28, 27, 27, 28, 27, 28, 27, 35, 27, 27, 28, 29, 27, 27, 28, 26, 27, 28, 28, 28, 27, 27, 27, 28, 32, 27, 28, 28, 29, 28, 28, 27, 28, 28, 30, 29, 28, 25, 27, 28, 30, 28, 30, 30, 28, 30, 30, 28, 29, 30, 28, 28, 26, 27, 28, 45, 36, 40, 28, 50, 45, 30, 45, 40, 30, 45, 45, 29, 45, 35, 40, 40, 30, 30, 30, 45, 40, 40, 40, 40, 40, 40, 35, 34, 49, 40, 30, 61, 35, 40, 30, 36, 35, 29, 27, 48, 28, 27, 27, 26, 27, 29, 27, 26, 27, 31, 27, 27, 28, 29, 28, 27, 28, 29, 38, 30, 26, 36, 40, 58, 57, 30, 33, 56, 35, 39, 37, 38, 46, 37, 39, 39, 45, 35, 46, 58, 65, 60, 45, 32, 36, 43, 32, 68, 39, 28, 31, 27, 28, 27, 37, 38, 30, 30, 28, 36, 45, 28, 26, 28, 28, 28, 27, 26, 28, 27, 26, 26, 27, 28, 31, 32, 37, 35, 29, 33, 35, 29, 41, 32, 36, 29, 28, 28, 28, 37, 36, 37, 35, 31, 32, 30, 27, 31, 32, 31, 33, 28, 33, 29, 27, 28, 31, 28, 31, 28, 34, 27, 27, 28, 27, 27, 27, 27, 26, 26, 26, 27, 27, 28, 26, 31, 26, 29, 31, 29, 29, 30, 29, 30, 31, 32, 29, 30, 27, 32, 27, 26, 31, 31, 31, 27, 27, 33, 27, 28, 28, 28, 26, 27, 27, 28, 30, 27, 27, 30, 29, 26, 27, 28, 27, 26, 26, 28, 27, 26, 28, 28, 26, 28, 27, 29, 27, 28, 28, 26, 26, 29, 28, 27, 27, 27, 28, 26, 25, 27, 29, 30, 36, 40, 28, 38, 26, 27, 27, 50, 27, 45, 27, 28, 26, 25, 35, 35, 44, 30, 27, 31, 27, 28, 27, 27, 28, 28, 28, 35, 33, 30, 28, 28, 29, 29, 36, 32, 36, 34, 32, 28, 28, 29, 28, 28, 32, 30, 35, 33, 36, 32, 30, 32, 36, 34) # 获取排序后的唯一值 unique_x = sort(unique(x)) n_unique = length(unique_x) # 生成所有可能的阈值组合(i < j) threshold_combinations = expand.grid(i = 1:(n_unique-1), j = 2:n_unique) threshold_combinations = threshold_combinations[threshold_combinations$i < threshold_combinations$j, ] # 定义函数计算每组大小及差异 calculate_group_diff = function(i, j) { t1 = unique_x[i] t2 = unique_x[j] g1 = sum(x <= t1) g2 = sum(x > t1 & x <= t2) g3 = sum(x > t2) group_sizes = c(g1, g2, g3) diff = max(group_sizes) - min(group_sizes) return(list(t1 = t1, t2 = t2, sizes = group_sizes, diff = diff)) } # 遍历所有组合,计算差异 results = apply(threshold_combinations, 1, function(row) { calculate_group_diff(row[1], row[2]) }) # 转换为数据框便于查看 results_df = do.call(rbind, lapply(results, function(x) { data.frame(t1 = x$t1, t2 = x$t2, g1 = x$sizes[1], g2 = x$sizes[2], g3 = x$sizes[3], diff = x$diff) })) # 找到差异最小的组合 min_diff = min(results_df$diff) best_thresholds = results_df[results_df$diff == min_diff, ] # 输出最优阈值及分组情况 cat("最优阈值组合:\n") print(best_thresholds) # 选择其中一组阈值进行分组 selected_t
相关产品推荐
相关产品推荐

