Pandas分组取calinski_harabasz最值及序列肘点提取方法
Pandas 聚类评分两阶段处理实现
原最大值规则实现
第一阶段:分组筛选
按num_clusters分组,每组保留calinski_harabasz最高行,重复值任意保留一条:
- 先按
num_clusters升序、calinski_harabasz降序排序 - 对
num_clusters+calinski_harabasz组合去重,每组保留第一条 - 重置索引得到第一阶段结果
import pandas as pd # 原始示例数据 df = pd.DataFrame([ [{'max_iter': 200, 'n_clusters': 2}, 2, 4209.697651], [{'max_iter': 700, 'n_clusters': 2}, 2, 4209.697651], [{'max_iter': 200, 'n_clusters': 3}, 3, 5334.854274], [{'max_iter': 700, 'n_clusters': 3}, 3, 5436.854274], [{'max_iter': 200, 'n_clusters': 4}, 4, 4702.497651], [{'max_iter': 700, 'n_clusters': 4}, 4, 4709.697651], [{'max_iter': 200, 'n_clusters': 5}, 5, 5636.855534], [{'max_iter': 700, 'n_clusters': 5}, 5, 5736.854274] ], columns=['params', 'num_clusters', 'calinski_harabasz']) # 第一阶段处理代码 df_phase1 = ( df.sort_values(['num_clusters', 'calinski_harabasz'], ascending=[True, False]) .drop_duplicates(subset=['num_clusters', 'calinski_harabasz'], keep='first') .reset_index(drop=True) )
运行后输出和预期第一阶段结果完全一致。
第二阶段:肘点提取
基于已经按num_clusters升序排列的第一阶段结果,提取首个下一行评分小于当前行的行:
# 用shift(-1)取到下一行的评分值,做布尔筛选后取第一个匹配项 target_idx = df_phase1[df_phase1['calinski_harabasz'].shift(-1) < df_phase1['calinski_harabasz']].index[0] df_elbow = df_phase1.loc[[target_idx]]
运行后输出num_clusters=3的对应行,和预期结果一致。
最小值场景改造方案
只需要调整排序方向和比对逻辑即可,核心流程不变:
第一阶段:分组保留每组最小值
将calinski_harabasz的排序方向改为升序,其余逻辑不变:
df_phase1_min = ( df.sort_values(['num_clusters', 'calinski_harabasz'], ascending=[True, True]) .drop_duplicates(subset=['num_clusters', 'calinski_harabasz'], keep='first') .reset_index(drop=True) )
第二阶段:提取首个上升拐点
将比对条件改为下一行评分大于当前行,其余逻辑不变:
target_idx_min = df_phase1_min[df_phase1_min['calinski_harabasz'].shift(-1) > df_phase1_min['calinski_harabasz']].index[0] df_elbow_min = df_phase1_min.loc[[target_idx_min]]
边界提示:如果数据存在极值点在最后一行的情况,建议在取索引前先判断筛选结果是否非空,避免抛出索引越界错误。
内容的提问来源于stack exchange,提问作者Carola
相关产品推荐
相关产品推荐

