Title: [ENH]: Better positioning of rotated tick labels · Issue #28951 · matplotlib/matplotlib · GitHub
Open Graph Title: [ENH]: Better positioning of rotated tick labels · Issue #28951 · matplotlib/matplotlib
X Title: [ENH]: Better positioning of rotated tick labels · Issue #28951 · matplotlib/matplotlib
Description: Problem Tick labels are currently centered, also with rotation: plt.bar(range(3), [1, 3, 2], tick_label=['very long tick labels'] * 3) plt.tick_params(rotation=30) The rotated labels do not "point" to the ticks anymore, which can make it...
Open Graph Description: Problem Tick labels are currently centered, also with rotation: plt.bar(range(3), [1, 3, 2], tick_label=['very long tick labels'] * 3) plt.tick_params(rotation=30) The rotated labels do not "point"...
X Description: Problem Tick labels are currently centered, also with rotation: plt.bar(range(3), [1, 3, 2], tick_label=['very long tick labels'] * 3) plt.tick_params(rotation=30) The rotated labels do not...
Opengraph URL: https://github.com/matplotlib/matplotlib/issues/28951
X: @github
Domain: github.com
{"@context":"https://schema.org","@type":"DiscussionForumPosting","headline":"[ENH]: Better positioning of rotated tick labels","articleBody":"### Problem\r\n\r\nTick labels are currently centered, also with rotation:\r\n\r\n```\r\nplt.bar(range(3), [1, 3, 2], tick_label=['very long tick labels'] * 3)\r\nplt.tick_params(rotation=30)\r\n```\r\n\r\n\r\nThe rotated labels do not \"point\" to the ticks anymore, which can make it difficult to see which label belongs to which tick - up to being outright misleading, e.g.\r\n\r\n```\r\nN = 20\r\nplt.bar(range(N), range(N), tick_label=[f'tick label {i}' for i in range(N)])\r\nplt.tick_params(rotation=45)\r\n```\r\n\r\n\r\nA common workaround is to adapt the alignment of the tick labels (e.g. demonstated in [this example](https://matplotlib.org/devdocs/gallery/ticks/date_concise_formatter.html#sphx-glr-gallery-ticks-date-concise-formatter-py)). The solution is not satisfying for two reasons:\r\n\r\n- The canonical way to adjust tick styles is `tick_params`, but we don't have alignment in there yet (and that has reasons, see https://github.com/matplotlib/matplotlib/issues/13774). Therefore people have to resort to setting the alignment on the individual tick instances, which has the major disadvantage that it does not work for dynamically changing plots because tick instances are volatile.\r\n- When rotating ticks, I expect that it \"just works\" and I don't have to additionally fine tune the result.\r\n\r\n### Proposed solution\r\n\r\nA new rotation algorithm that rotates the ticks appropriately. We can include this as a new `rotation_mode` type (see [Text.set_rotation_mode](https://matplotlib.org/stable/api/text_api.html#matplotlib.text.Text.set_rotation_mode)).\r\n\r\nEssentially, the labels should \"point\" towards their ticks. Note that this results in a very particular alignment: -90°, 0° and 90° want a centered alignment, whereas diagonal tick labels want a left/right alignment.\r\n\r\nOne can get approximately good results by tuning the alignment depending on the angle.\r\n\r\n\u003cdetails\u003e\r\n\u003csummary\u003eExample code (color coding for alignment: black: 'center', green: 'right', red: 'left')\u003c/summary\u003e\r\n\r\n```\r\nimport matplotlib.pyplot as plt\r\nimport numpy as np\r\n\r\n\r\ndef ha_for_angle(angle):\r\n if angle \u003c -90 or angle \u003e 90:\r\n raise ValueError('Todo: not thought about reasonable values for upside-down labels')\r\n if angle \u003c -60:\r\n return 'center'\r\n if angle \u003c -5:\r\n return 'left'\r\n if angle \u003c= 5:\r\n return 'center'\r\n if angle \u003c= 60:\r\n return 'right'\r\n if angle \u003c= 90:\r\n return 'center'\r\n \r\n\r\nfig, ax = plt.subplots(figsize=(18, 1))\r\nangles = np.linspace(90, -90, 37)\r\nN = len(angles)\r\nax.set_xticks(range(N), ['label']*N)\r\nax.set_xlim(-0.5, N -0.5)\r\ntls = ax.xaxis.get_majorticklabels()\r\nfor ticklabel, angle in zip(tls, angles):\r\n ha = ha_for_angle(angle)\r\n color = {'left': 'r', 'center': 'k', 'right': 'g'}[ha]\r\n ticklabel.set(rotation=angle, ha=ha, color=color)\r\n```\r\n\r\n\u003c/details\u003e\r\n\r\n\r\n\r\n\r\nWhile one could try and come up with mathematical more accurate text position methods, this simple trick gives reasonably good results.\r\n\r\n**Concrete suggestion:** Introduce rotation modes \"xtick\", \"ytick\" (exact names t.b.d.). \"xtick\" ignores the horizontal alignment setting and instead chooses a suitable one depending on the angle as above. Likewise \"ytick\" chooses a suitable vertical alignment.\r\n\r\nDepending on how strong we feel about backward compatibility, we can either make these rotation modes the default for ticks. Or we are defensive and only add it to `tick_params` for now, so that one could write `ax.xaxis.tick_params(rotation=45, rotation_mode='xtick')`.","author":{"url":"https://github.com/timhoffm","@type":"Person","name":"timhoffm"},"datePublished":"2024-10-07T20:38:28.000Z","interactionStatistic":{"@type":"InteractionCounter","interactionType":"https://schema.org/CommentAction","userInteractionCount":4},"url":"https://github.com/28951/matplotlib/issues/28951"}
| route-pattern | /_view_fragments/issues/show/:user_id/:repository/:id/issue_layout(.:format) |
| route-controller | voltron_issues_fragments |
| route-action | issue_layout |
| fetch-nonce | v2:9efdd54c-8c88-0bed-8bc4-9343dde2ecfd |
| current-catalog-service-hash | 81bb79d38c15960b92d99bca9288a9108c7a47b18f2423d0f6438c5b7bcd2114 |
| request-id | 84D6:1FCD98:1FE6F9B:2A4C616:6A51EB31 |
| html-safe-nonce | a4ca55e85f10d4b5654bcffa4b3c31bd588c94ce35c99355e1b6a9a3da2add9d |
| visitor-payload | eyJyZWZlcnJlciI6IiIsInJlcXVlc3RfaWQiOiI4NEQ2OjFGQ0Q5ODoxRkU2RjlCOjJBNEM2MTY6NkE1MUVCMzEiLCJ2aXNpdG9yX2lkIjoiNzAxNzY4NDA5MjIyODY3NzYxIiwicmVnaW9uX2VkZ2UiOiJpYWQiLCJyZWdpb25fcmVuZGVyIjoiaWFkIn0= |
| visitor-hmac | d0405db0e6a2137018cebe1582c5b4309f8f72c24a16dda0db8a7ad1e9237484 |
| hovercard-subject-tag | issue:2571426096 |
| github-keyboard-shortcuts | repository,issues,copilot |
| google-site-verification | Apib7-x98H0j5cPqHWwSMm6dNU4GmODRoqxLiDzdx9I |
| octolytics-url | https://collector.github.com/github/collect |
| analytics-location | / |
| fb:app_id | 1401488693436528 |
| apple-itunes-app | app-id=1477376905, app-argument=https://github.com/_view_fragments/issues/show/matplotlib/matplotlib/28951/issue_layout |
| twitter:image | https://opengraph.githubassets.com/896b454008bb9c97d119cfaaf55f063d5effe3f76e249c93f77e8501bc662532/matplotlib/matplotlib/issues/28951 |
| twitter:card | summary_large_image |
| og:image | https://opengraph.githubassets.com/896b454008bb9c97d119cfaaf55f063d5effe3f76e249c93f77e8501bc662532/matplotlib/matplotlib/issues/28951 |
| og:image:alt | Problem Tick labels are currently centered, also with rotation: plt.bar(range(3), [1, 3, 2], tick_label=['very long tick labels'] * 3) plt.tick_params(rotation=30) The rotated labels do not "point"... |
| og:image:width | 1200 |
| og:image:height | 600 |
| og:site_name | GitHub |
| og:type | object |
| og:author:username | timhoffm |
| hostname | github.com |
| expected-hostname | github.com |
| None | b9a586c06a05a7a86fc7e3f4dbd03e42f6869085879aa184aa6369456dbd50fb |
| turbo-cache-control | no-preview |
| go-import | github.com/matplotlib/matplotlib git https://github.com/matplotlib/matplotlib.git |
| octolytics-dimension-user_id | 215947 |
| octolytics-dimension-user_login | matplotlib |
| octolytics-dimension-repository_id | 1385122 |
| octolytics-dimension-repository_nwo | matplotlib/matplotlib |
| octolytics-dimension-repository_public | true |
| octolytics-dimension-repository_is_fork | false |
| octolytics-dimension-repository_network_root_id | 1385122 |
| octolytics-dimension-repository_network_root_nwo | matplotlib/matplotlib |
| turbo-body-classes | logged-out env-production page-responsive |
| disable-turbo | false |
| browser-stats-url | https://api.github.com/_private/browser/stats |
| browser-errors-url | https://api.github.com/_private/browser/errors |
| release | 7aed05249554b889eb33d002851a973eebcc7e91 |
| ui-target | full |
| theme-color | #1e2327 |
| color-scheme | light dark |
Links:
Viewport: width=device-width