@@ -3601,7 +3601,7 @@ def _chart_by_model(model_tier: Dict[str, Counter], plt_mod) -> Optional[str]:
36013601 if len (ordered ) <= top_n :
36023602 models = [m for m , _ in ordered ]
36033603 per_model : Dict [str , Counter ] = {m : model_tier [m ] for m in models }
3604- title = "按 request_model 堆叠分档(每段数字为该档条数 )"
3604+ title = "按 request_model 堆叠分档(每段数字为该档占比 )"
36053605 else :
36063606 models = [m for m , _ in ordered [:top_n ]]
36073607 per_model = {m : model_tier [m ] for m in models }
@@ -3611,38 +3611,87 @@ def _chart_by_model(model_tier: Dict[str, Counter], plt_mod) -> Optional[str]:
36113611 models .append (other_label )
36123612 per_model [other_label ] = other_c
36133613 title = (
3614- f"按 request_model 堆叠分档(Top { top_n } 请求量 + 其余合并;每段数字为该档条数 )"
3614+ f"按 request_model 堆叠分档(Top { top_n } 请求量 + 其余合并;每段数字为该档占比 )"
36153615 )
36163616 fig , ax = plt_mod .subplots (figsize = (max (6 , len (models ) * 0.9 ), 3.8 ))
36173617 n = len (models )
36183618 x = list (range (n ))
36193619 w = 0.65
36203620 bottom = [0.0 ] * n
36213621 colors = {"high_precision" : "#c0392b" , "watchlist" : "#f39c12" , "none" : "#bdc3c7" }
3622+ _tier_legend_zh = {
3623+ "high_precision" : "高置信异常样本(Bad Case)" ,
3624+ "watchlist" : "待观察样本(不完美交互)" ,
3625+ "none" : "正常样本(高质量交互)" ,
3626+ }
3627+ # Pre-compute per-model totals for ratio calculation
3628+ model_totals = [sum (per_model [m ].values ()) for m in models ]
3629+ # Collect all (i, yc, label, v, col_total) for deferred label rendering
3630+ # to allow visibility filtering based on bar height proportion
3631+ label_tasks : List [tuple ] = [] # (xi, yc, text, v, col_total)
36223632 for tier in tiers :
36233633 vs = [float (per_model [m ].get (tier , 0 )) for m in models ]
36243634 if not any (vs ):
36253635 continue
3626- leg = f" { _tier_zh (tier ) } ( { tier } )"
3636+ leg = _tier_legend_zh . get (tier , tier )
36273637 ax .bar (x , vs , bottom = bottom , label = leg , color = colors [tier ], width = w )
3628- vmax = max (vs ) if vs else 1.0
36293638 for i , v in enumerate (vs ):
36303639 if v > 0 :
36313640 yc = bottom [i ] + v / 2.0
3632- ax .text (
3633- x [i ],
3634- yc ,
3635- str (int (v )),
3636- ha = "center" ,
3637- va = "center" ,
3638- fontsize = 9 ,
3639- color = "white" if v >= vmax * 0.25 else "#222" ,
3640- )
3641+ label_tasks .append ((x [i ], yc , v , model_totals [i ]))
36413642 bottom = [b + v for b , v in zip (bottom , vs )]
3643+ # Determine figure height in data units for min-height threshold
3644+ col_max = max (bottom ) if bottom else 1.0
3645+ # Minimum segment height (as fraction of tallest column) to show label inline;
3646+ # segments shorter than this get their label placed just above the segment.
3647+ MIN_RATIO_FOR_INLINE = 0.08
3648+ for xi , yc , v , col_total in label_tasks :
3649+ ratio = v / col_total if col_total > 0 else 0.0
3650+ label_text = f"{ ratio :.0%} "
3651+ seg_height_frac = v / col_max if col_max > 0 else 0.0
3652+ if seg_height_frac >= MIN_RATIO_FOR_INLINE :
3653+ # Segment tall enough: render label centred inside the bar segment
3654+ ax .text (
3655+ xi ,
3656+ yc ,
3657+ label_text ,
3658+ ha = "center" ,
3659+ va = "center" ,
3660+ fontsize = 8 ,
3661+ color = "white" ,
3662+ )
3663+ else :
3664+ # Segment too short: render small label just above the segment top,
3665+ # slightly offset to avoid overlap with neighbouring text
3666+ seg_top = yc + v / 2.0
3667+ ax .text (
3668+ xi ,
3669+ seg_top + col_max * 0.012 ,
3670+ label_text ,
3671+ ha = "center" ,
3672+ va = "bottom" ,
3673+ fontsize = 7 ,
3674+ color = "#555" ,
3675+ )
3676+ # Annotate the total sample count above each stacked bar
3677+ for i , total in enumerate (model_totals ):
3678+ if total > 0 :
3679+ ax .text (
3680+ x [i ],
3681+ bottom [i ] + col_max * 0.015 ,
3682+ str (int (total )),
3683+ ha = "center" ,
3684+ va = "bottom" ,
3685+ fontsize = 8 ,
3686+ fontweight = "bold" ,
3687+ color = "#333" ,
3688+ )
3689+ # Extend y-axis upper limit so the top-bar annotations are not clipped
3690+ ax .set_ylim (0 , col_max * 1.12 )
36423691 ax .set_xticks (x )
36433692 ax .set_xticklabels (models )
36443693 ax .set_title (title )
3645- ax .set_ylabel ("条数 " )
3694+ ax .set_ylabel ("样本数目 " )
36463695 ax .legend ()
36473696 plt_mod .setp (ax .xaxis .get_majorticklabels (), rotation = 30 , ha = "right" )
36483697 fig .tight_layout ()
0 commit comments