@@ -2381,7 +2381,8 @@ def bar(self, x, height, width=0.8, bottom=None, *, align="center",
23812381
23822382 self ._request_autoscale_view ()
23832383
2384- bar_container = BarContainer (patches , errorbar , label = label )
2384+ bar_container = BarContainer (patches , errorbar , orientation ,
2385+ label = label )
23852386 self .add_container (bar_container )
23862387
23872388 if tick_labels is not None :
@@ -2497,6 +2498,136 @@ def barh(self, y, width, height=0.8, left=None, *, align="center",
24972498 align = align , ** kwargs )
24982499 return patches
24992500
2501+ def blabel (self , container , captions = [], fmt = "%g" , mode = "edge" ,
2502+ padding = None , shifting = 0 , autoscale = True , ** kwargs ):
2503+ """
2504+ Label a bar plot.
2505+
2506+ Adds labels to bars in the given `BarContainer`.
2507+
2508+ Parameters
2509+ ----------
2510+ container : `.BarContainer`
2511+ Container with all the bars and optionally errorbars.
2512+
2513+ captions : array-like, optional
2514+ A list of label texts, that should be displayed. If not given, the
2515+ label texts will be the data values formatted with *fmt*.
2516+
2517+ fmt : str, optional
2518+ A format string for the label. Default is '%g'
2519+
2520+ mode : {'edge', 'center'}, optional, default: 'edge'
2521+ Position of the label relative to the bar:
2522+
2523+ - 'edge': Placed at edge, the cumulative values will be shown.
2524+ - 'center': Placed at center, the individual values will be shown.
2525+
2526+ padding : float, optional
2527+ Space in points for label to leave the edge of the bar.
2528+
2529+ shifting : float, optional
2530+ Translation in points for label to leave the center of the bar.
2531+
2532+ autoscale : bool, optional
2533+ If ``True``, try to rescale to fit the labels. Default is ``True``.
2534+
2535+ Returns
2536+ -------
2537+ annotations
2538+ A list of `.Text` instances for the labels.
2539+ """
2540+ def nonefill (a , n ):
2541+ return list (a ) + [None ] * (n - len (a ))
2542+
2543+ def sign (x ):
2544+ return 1 if x >= 0 else - 1
2545+
2546+ if mode == "edge" :
2547+ padding = padding or 3
2548+ elif mode == "center" :
2549+ padding = padding or 0
2550+
2551+ bars = container .patches
2552+ errorbar = container .errorbar
2553+ orientation = container .orientation
2554+
2555+ N = len (bars )
2556+ if errorbar :
2557+ lines = errorbar .lines
2558+ barlinecols = lines [2 ]
2559+ barlinecol = barlinecols [0 ]
2560+ segments = barlinecol .get_segments ()
2561+ errs = nonefill (segments , N )
2562+ else :
2563+ errs = nonefill ([], N )
2564+ caps = nonefill (captions , N )
2565+
2566+ annotations = []
2567+ for bar , err , cap in zip (bars , errs , caps ):
2568+
2569+ (x0 , y0 ), (x1 , y1 ) = bar .get_bbox ().get_points ()
2570+ xc , yc = (x0 + x1 ) / 2 , (y0 + y1 ) / 2
2571+
2572+ if orientation == "vertical" :
2573+ extrema = max (y0 , y1 ) if yc >= 0 else min (y0 , y1 )
2574+ length = abs (y0 - y1 )
2575+ elif orientation == "horizontal" :
2576+ extrema = max (x0 , x1 ) if xc >= 0 else min (x0 , x1 )
2577+ length = abs (x0 - x1 )
2578+
2579+ if err is None :
2580+ endpt = extrema
2581+ elif orientation == "vertical" :
2582+ endpt = err [:, 1 ].max () if yc >= 0 else err [:, 1 ].min ()
2583+ elif orientation == "horizontal" :
2584+ endpt = err [:, 0 ].max () if xc >= 0 else err [:, 0 ].min ()
2585+
2586+ if mode == "center" :
2587+ value = sign (extrema ) * length
2588+ elif mode == "edge" :
2589+ value = extrema
2590+
2591+ if mode == "center" :
2592+ xy = xc , yc
2593+ elif mode == "edge" and orientation == "vertical" :
2594+ xy = xc , endpt
2595+ elif mode == "edge" and orientation == "horizontal" :
2596+ xy = endpt , yc
2597+
2598+ if orientation == "vertical" :
2599+ xytext = shifting , sign (extrema ) * padding
2600+ else :
2601+ xytext = sign (extrema ) * padding , shifting
2602+
2603+ if mode == "center" :
2604+ ha , va = "center" , "center"
2605+ elif mode == "edge" and orientation == "vertical" and yc >= 0 :
2606+ ha , va = "center" , "bottom"
2607+ elif mode == "edge" and orientation == "vertical" and yc < 0 :
2608+ ha , va = "center" , "top"
2609+ elif mode == "edge" and orientation == "horizontal" and xc >= 0 :
2610+ ha , va = "left" , "center"
2611+ elif mode == "edge" and orientation == "horizontal" and xc < 0 :
2612+ ha , va = "right" , "center"
2613+
2614+ annotation = self .annotate (cap or fmt % value , xy , xytext ,
2615+ textcoords = "offset points" ,
2616+ ha = ha , va = va , ** kwargs )
2617+ annotations .append (annotation )
2618+
2619+ if autoscale :
2620+ transform = self .transData .inverted ()
2621+ renderer = self .figure .canvas .get_renderer ()
2622+ corners = []
2623+ for text in annotations :
2624+ points = text .get_window_extent (renderer ).get_points ()
2625+ corners .append (transform .transform (points ))
2626+ self .update_datalim (np .vstack (corners ))
2627+ self .autoscale_view ()
2628+
2629+ return annotations
2630+
25002631 @_preprocess_data ()
25012632 @docstring .dedent_interpd
25022633 def broken_barh (self , xranges , yrange , ** kwargs ):
0 commit comments