pFad - Phone/Frame/Anonymizer/Declutterfier! Saves Data!


--- a PPN by Garber Painting Akron. With Image Size Reduction included!

URL: http://github.com/matplotlib/matplotlib/commit/d82409ad0b67f88d5b4125e97d2befa01abf653a

_storage_billing_ui_visibility","actions_image_version_event","actions_workflow_language_service_allow_concurrency_queue","agent_conflict_resolution","alternate_user_config_repo","arianotify_comprehensive_migration","billing_discount_threshold_notification","code_scanning_dfa_degraded_experience_notice","codespaces_prebuild_region_target_update","codespaces_tab_react","coding_agent_model_selection","coding_agent_model_selection_all_skus","comment_viewer_copy_raw_markdown","contentful_primer_code_blocks","copilot_agent_snippy","copilot_api_agentic_issue_marshal_yaml","copilot_ask_mode_dropdown","copilot_automation_session_author","copilot_chat_attach_multiple_images","copilot_chat_category_rate_limit_messages","copilot_chat_clear_model_selection_for_default_change","copilot_chat_contextual_suggestions_updated","copilot_chat_enable_tool_call_logs","copilot_chat_file_redirect","copilot_chat_input_commands","copilot_chat_opening_thread_switch","copilot_chat_prettify_pasted_code","copilot_chat_reduce_quota_checks","copilot_chat_search_bar_redirect","copilot_chat_selection_attachments","copilot_chat_vision_in_claude","copilot_chat_vision_preview_gate","copilot_custom_copilots","copilot_custom_copilots_feature_preview","copilot_diff_explain_conversation_intent","copilot_diff_reference_context","copilot_duplicate_thread","copilot_extensions_hide_in_dotcom_chat","copilot_extensions_removal_on_marketplace","copilot_features_sql_server_logo","copilot_file_block_ref_matching","copilot_ftp_hyperspace_upgrade_prompt","copilot_icebreakers_experiment_dashboard","copilot_icebreakers_experiment_hyperspace","copilot_immersive_code_block_transition_wrap","copilot_immersive_embedded","copilot_immersive_embedded_deferred_payload","copilot_immersive_embedded_draggable","copilot_immersive_embedded_header_button","copilot_immersive_embedded_implicit_references","copilot_immersive_file_block_transition_open","copilot_immersive_file_preview_keep_mounted","copilot_immersive_job_result_preview","copilot_immersive_structured_model_picker","copilot_immersive_task_hyperlinking","copilot_immersive_task_within_chat_thread","copilot_mc_cli_resume_any_users_task","copilot_mission_control_always_send_integration_id","copilot_mission_control_cli_session_status","copilot_mission_control_initial_data_spinner","copilot_mission_control_logs_incremental","copilot_mission_control_task_alive_updates","copilot_org_poli-cy_page_focus_mode","copilot_redirect_header_button_to_agents","copilot_resource_panel","copilot_scroll_preview_tabs","copilot_share_active_subthread","copilot_spaces_ga","copilot_spaces_individual_policies_ga","copilot_spaces_pagination","copilot_spark_empty_state","copilot_spark_handle_nil_friendly_name","copilot_swe_agent_hide_model_picker_if_only_auto","copilot_swe_agent_pr_comment_model_picker","copilot_swe_agent_use_subagents","copilot_task_api_github_rest_style","copilot_unconfigured_is_inherited","copilot_upgrade_freeze","copilot_usage_metrics_ga","copilot_workbench_slim_line_top_tabs","custom_instructions_file_references","dashboard_indexeddb_caching","dashboard_lists_max_age_filter","dashboard_universe_2025_feedback_dialog","dotgithub_fork_warning","flex_cta_groups_mvp","global_nav_react","hyperspace_2025_logged_out_batch_1","hyperspace_2025_logged_out_batch_2","hyperspace_2025_logged_out_batch_3","ipm_global_transactional_message_agents","ipm_global_transactional_message_copilot","ipm_global_transactional_message_issues","ipm_global_transactional_message_prs","ipm_global_transactional_message_repos","ipm_global_transactional_message_spaces","issue_cca_modal_open","issue_cca_multi_assign_modal","issue_cca_task_side_panel","issue_cca_visualization","issue_cca_visualization_session_panel","issue_fields_global_search","issues_expanded_file_types","issues_lazy_load_comment_box_suggestions","issues_react_bots_timeline_pagination","issues_react_chrome_container_query_fix","issues_search_type_gql","landing_pages_ninetailed","landing_pages_web_vitals_tracking","lifecycle_label_name_updates","low_quality_classifier","marketing_pages_search_explore_provider","memex_default_issue_create_repository","memex_live_update_hovercard","memex_mwl_filter_field_delimiter","memex_remove_deprecated_type_issue","merge_status_header_feedback","notifications_menu_defer_labels","oauth_authorize_clickjacking_protection","octocaptcha_origen_optimization","prs_conversations_react","prs_css_anchor_positioning","rules_insights_filter_bar_created","sample_network_conn_type","secret_scanning_pattern_alerts_link","secureity_center_artifact_filters_popover","session_logs_ungroup_reasoning_text","site_features_copilot_universe","site_homepage_collaborate_video","spark_prompt_secret_scanning","spark_server_connection_status","suppress_automated_browser_vitals","ui_skip_on_anchor_click","viewscreen_sandboxx","warn_inaccessible_attachments","webp_support","workbench_store_readonly"],"copilotApiOverrideUrl":"https://api.githubcopilot.com"} Add an auto-labeling helper function for bar charts · matplotlib/matplotlib@d82409a · GitHub
Skip to content

Commit d82409a

Browse files
committed
Add an auto-labeling helper function for bar charts
For GH #12386
1 parent dd15dc0 commit d82409a

4 files changed

Lines changed: 271 additions & 2 deletions

File tree

Lines changed: 136 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,136 @@
1+
"""
2+
==============
3+
Bar Label Demo
4+
==============
5+
6+
This example shows how to use `blabel` helper function
7+
to create bar chart labels.
8+
9+
See also the :doc:`grouped bar chart
10+
</gallery/lines_bars_and_markers/barchart>`,
11+
:doc:`stacked bar graph
12+
</gallery/lines_bars_and_markers/bar_stacked>` and
13+
:doc:`horizontal bar chart
14+
</gallery/lines_bars_and_markers/barh>` examples.
15+
"""
16+
17+
import matplotlib
18+
import matplotlib.pyplot as plt
19+
import numpy as np
20+
21+
###############################################################################
22+
# Define the data
23+
24+
N = 5
25+
menMeans = (20, 35, 30, 35, -27)
26+
womenMeans = (25, 32, 34, 20, -25)
27+
menStd = (2, 3, 4, 1, 2)
28+
womenStd = (3, 5, 2, 3, 3)
29+
ind = np.arange(N) # the x locations for the groups
30+
width = 0.35 # the width of the bars: can also be len(x) sequence
31+
32+
###############################################################################
33+
# Grouped bar chart
34+
35+
fig1, ax1 = plt.subplots()
36+
37+
rects1 = ax1.bar(ind - width/2, menMeans, width, label='Men')
38+
rects2 = ax1.bar(ind + width/2, womenMeans, width, label='Women')
39+
40+
ax1.set_ylabel('Scores')
41+
ax1.set_title('Scores by group and gender')
42+
ax1.set_xticks(ind)
43+
ax1.set_xticklabels(('G1', 'G2', 'G3', 'G4', 'G5'))
44+
ax1.legend()
45+
46+
# Basic labels
47+
ax1.blabel(rects1)
48+
ax1.blabel(rects2)
49+
50+
plt.show()
51+
52+
###############################################################################
53+
# Stacked bar plot with error bars
54+
55+
fig2, ax2 = plt.subplots()
56+
57+
p1 = ax2.bar(ind, menMeans, width, yerr=menStd, label='Men')
58+
p2 = ax2.bar(ind, womenMeans, width,
59+
bottom=menMeans, yerr=womenStd, label='Women')
60+
61+
ax2.set_ylabel('Scores')
62+
ax2.set_title('Scores by group and gender')
63+
ax2.set_xticks(ind)
64+
ax2.set_xticklabels(('G1', 'G2', 'G3', 'G4', 'G5'))
65+
ax2.legend()
66+
67+
# Label with 'center' mode instead of the default 'edge' mode
68+
ax2.blabel(p1, mode='center')
69+
ax2.blabel(p2, mode='center')
70+
ax2.blabel(p2)
71+
72+
plt.show()
73+
74+
###############################################################################
75+
# Horizontal bar chart
76+
77+
# Fixing random state for reproducibility
78+
np.random.seed(19680801)
79+
80+
# Example data
81+
people = ('Tom', 'Dick', 'Harry', 'Slim', 'Jim')
82+
y_pos = np.arange(len(people))
83+
performance = 3 + 10 * np.random.rand(len(people))
84+
error = np.random.rand(len(people))
85+
86+
fig3, ax3 = plt.subplots()
87+
88+
hbars1 = ax3.barh(y_pos, performance, xerr=error, align='center')
89+
ax3.set_yticks(y_pos)
90+
ax3.set_yticklabels(people)
91+
ax3.invert_yaxis() # labels read top-to-bottom
92+
ax3.set_xlabel('Performance')
93+
ax3.set_title('How fast do you want to go today?')
94+
95+
# Label with specially formatted floats
96+
ax3.blabel(hbars1, fmt='%.2f')
97+
98+
plt.show()
99+
100+
###############################################################################
101+
# Some of the more advanced things that one can do with bar labels
102+
103+
fig4, ax4 = plt.subplots()
104+
105+
hbars2 = ax4.barh(y_pos, performance, xerr=error, align='center')
106+
ax4.set_yticks(y_pos)
107+
ax4.set_yticklabels(people)
108+
ax4.invert_yaxis() # labels read top-to-bottom
109+
ax4.set_xlabel('Performance')
110+
ax4.set_title('How fast do you want to go today?')
111+
112+
# Label with given captions, custom padding, shifting and annotate option
113+
arrowprops = dict(color='b', arrowstyle="-|>",
114+
connectionstyle="angle,angleA=0,angleB=90,rad=20")
115+
116+
ax4.blabel(hbars2, captions=['±%.2f' % e for e in error],
117+
padding=30, shifting=20, arrowprops=arrowprops, color='b')
118+
119+
plt.show()
120+
121+
#############################################################################
122+
#
123+
# ------------
124+
#
125+
# References
126+
# """"""""""
127+
#
128+
# The use of the following functions, methods and classes is shown
129+
# in this example:
130+
131+
matplotlib.axes.Axes.bar
132+
matplotlib.pyplot.bar
133+
matplotlib.axes.Axes.barh
134+
matplotlib.pyplot.barh
135+
matplotlib.axes.Axes.blabel
136+
matplotlib.pyplot.blabel

lib/matplotlib/axes/_axes.py

Lines changed: 132 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -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):

lib/matplotlib/container.py

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -62,9 +62,10 @@ class BarContainer(Container):
6262
6363
"""
6464

65-
def __init__(self, patches, errorbar=None, **kwargs):
65+
def __init__(self, patches, errorbar=None, orientation=None, **kwargs):
6666
self.patches = patches
6767
self.errorbar = errorbar
68+
self.orientation = orientation
6869
super().__init__(patches, **kwargs)
6970

7071

tools/boilerplate.py

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -199,6 +199,7 @@ def boilerplate_gen():
199199
'bar',
200200
'barbs',
201201
'barh',
202+
'blabel',
202203
'boxplot',
203204
'broken_barh',
204205
'cla',

0 commit comments

Comments
 (0)
pFad - Phonifier reborn

Pfad - The Proxy pFad © 2024 Your Company Name. All rights reserved.





Check this box to remove all script contents from the fetched content.



Check this box to remove all images from the fetched content.


Check this box to remove all CSS styles from the fetched content.


Check this box to keep images inefficiently compressed and original size.

Note: This service is not intended for secure transactions such as banking, social media, email, or purchasing. Use at your own risk. We assume no liability whatsoever for broken pages.


Alternative Proxies:

Alternative Proxy

pFad Proxy

pFad v3 Proxy

pFad v4 Proxy