R中使用head/tails分类法如何指定7个分类数量?
问题根源
classInt包的classIntervals函数在style = "headtails"(头尾分类)模式下,n参数不是强制输出的分类数,仅为算法允许的最大分类数上限;thr是偏度终止阈值,两个参数都无法精准控制输出分类数为固定值。
头尾分类原生逻辑是迭代拆分:
- 每次取当前数值子集的均值,将子集拆分为低于均值(尾)、高于均值(头)两部分
- 若拆分出的子集偏度大于
thr设定的阈值,就继续对子集重复拆分操作 - 直到所有子集偏度均低于
thr,或拆分次数达到n设定的最大分类数上限才停止
这就是为什么调参只会出2类或14类:thr设得偏大时,拆2次就满足偏度要求直接终止,输出2类;thr设得偏小时,会一直拆分直到碰到设置的最大类数上限,输出14类。靠调整0-1区间的thr值,无法在任意分布的数据集上精准得到7个分类,因为分类数完全由数据本身的偏度分布决定,和thr没有固定对应关系。
7类分类的实现方法
直接改写迭代终止条件即可:保留头尾分类「按区间均值拆分」的核心逻辑,把终止条件从「子集偏度达标」改成「拆分到目标分类数就停止」,输出结果和原生classIntervals格式完全兼容:
library(classInt) # 自定义固定分类数的头尾分类函数 ht_fixed_classes <- function(x, target_n = 7) { # 初始化断点为全局最小值、最大值,自动忽略缺失值 breaks <- c(min(x, na.rm = T), max(x, na.rm = T)) # 迭代拆分直到断点数量满足n类要求(n类对应n+1个断点) while (length(breaks) < target_n + 1) { # 标记每个值所属的当前区间 interval_id <- findInterval(x, breaks, rightmost.closed = T) # 计算每个区间的均值作为新断点 add_breaks <- tapply(x, interval_id, mean) # 合并新断点、去重后排序 breaks <- sort(unique(c(breaks, add_breaks))) } # 返回和原生classIntervals格式一致的结果 classIntervals(x, n = target_n, style = "fixed", fixedBreaks = breaks) } # 测试:用提供的样例数据输出7类结果 test_vec <- c(4.15732383728027, 4.64473390579224, 5.13697910308838, 5.62461566925049, 6.08347082138062, 6.09681606292725, 5.98013210296631, 5.85955047607422, 5.74385595321655, 5.69291543960571, 5.80153608322144, 5.94426155090332, 6.10236692428589, 6.24384021759033, 4.13175535202026, 4.61712312698364, 5.10912799835205, 5.60870552062988, 6.10747909545898) ht_result_7 <- ht_fixed_classes(test_vec, target_n = 7) print(ht_result_7) # 10000+条原始数据直接替换传入向量即可 # block.data = read.csv("path/values.csv") # vec1 <- block.data$X4 # ht_result_7 <- ht_fixed_classes(vec1, target_n = 7)
注意事项
- 该实现完全遵循头尾分类的核心拆分规则,仅修改了终止条件,不会改变分类方法的本质逻辑
- 代码内置了断点去重逻辑,如果数据存在大量重复值导致无法凑够7个有效断点,说明数据分布本身不支持拆出7个有区分度的类别,需要先对重复值做预处理。
内容的提问来源于stack exchange,提问作者Nikos
相关产品推荐
相关产品推荐

