Title: Radar Chart with Polygonal Grid Lines · Issue #19981 · matplotlib/matplotlib · GitHub
Open Graph Title: Radar Chart with Polygonal Grid Lines · Issue #19981 · matplotlib/matplotlib
X Title: Radar Chart with Polygonal Grid Lines · Issue #19981 · matplotlib/matplotlib
Description: Bug report Bug summary I was able to create radar charts with polygonal grid lines before. But the code is now producing circular grid lines. It was working in version 3.2.x but since 3.3.0 the grid lines are circular. The official examp...
Open Graph Description: Bug report Bug summary I was able to create radar charts with polygonal grid lines before. But the code is now producing circular grid lines. It was working in version 3.2.x but since 3.3.0 the gri...
X Description: Bug report Bug summary I was able to create radar charts with polygonal grid lines before. But the code is now producing circular grid lines. It was working in version 3.2.x but since 3.3.0 the gri...
Opengraph URL: https://github.com/matplotlib/matplotlib/issues/19981
X: @github
Domain: github.com
{"@context":"https://schema.org","@type":"DiscussionForumPosting","headline":"Radar Chart with Polygonal Grid Lines","articleBody":"\u003c!--To help us understand and resolve your issue, please fill out the form to the best of your ability.--\u003e\r\n\u003c!--You can feel free to delete the sections that do not apply.--\u003e\r\n\r\n### Bug report\r\n\r\n**Bug summary**\r\n\r\nI was able to create radar charts with polygonal grid lines before. But the code is now producing circular grid lines.\r\nIt was working in version 3.2.x but since 3.3.0 the grid lines are circular. The [official example](https://matplotlib.org/stable/gallery/specialty_plots/radar_chart.html) appears to be the same in all the versions and still reads:\r\n\r\n\u003e It's possible to get a polygon grid by setting GRIDLINE_INTERPOLATION_STEPS in matplotlib.axis to the desired number of vertices, but the orientation of the polygon is not aligned with the radial axes.\r\n\r\nHowever, it is not working in the same manner as before.\r\n\r\n**Code for reproduction**\r\n\r\n\u003c!--A minimum code snippet required to reproduce the bug.\r\nPlease make sure to minimize the number of dependencies required, and provide\r\nany necessary plotted data.\r\nAvoid using threads, as Matplotlib is (explicitly) not thread-safe.--\u003e\r\nThe code below is the same as in the official example (link above) plus the method 'draw' which used to make the grid lines polygonal.\r\n\r\n\r\n```python\r\nimport numpy as np\r\n\r\nimport matplotlib.pyplot as plt\r\nfrom matplotlib.patches import Circle, RegularPolygon\r\nfrom matplotlib.path import Path\r\nfrom matplotlib.projections.polar import PolarAxes\r\nfrom matplotlib.projections import register_projection\r\nfrom matplotlib.spines import Spine\r\nfrom matplotlib.transforms import Affine2D\r\n\r\n\r\ndef radar_factory(num_vars, frame='circle'):\r\n \"\"\"\r\n Create a radar chart with `num_vars` axes.\r\n\r\n This function creates a RadarAxes projection and registers it.\r\n\r\n Parameters\r\n ----------\r\n num_vars : int\r\n Number of variables for radar chart.\r\n frame : {'circle', 'polygon'}\r\n Shape of frame surrounding axes.\r\n\r\n \"\"\"\r\n # calculate evenly-spaced axis angles\r\n theta = np.linspace(0, 2*np.pi, num_vars, endpoint=False)\r\n\r\n class RadarAxes(PolarAxes):\r\n\r\n name = 'radar'\r\n # use 1 line segment to connect specified points\r\n RESOLUTION = 1\r\n\r\n def __init__(self, *args, **kwargs):\r\n super().__init__(*args, **kwargs)\r\n # rotate plot such that the first axis is at the top\r\n self.set_theta_zero_location('N')\r\n\r\n def fill(self, *args, closed=True, **kwargs):\r\n \"\"\"Override fill so that line is closed by default\"\"\"\r\n return super().fill(closed=closed, *args, **kwargs)\r\n\r\n def plot(self, *args, **kwargs):\r\n \"\"\"Override plot so that line is closed by default\"\"\"\r\n lines = super().plot(*args, **kwargs)\r\n for line in lines:\r\n self._close_line(line)\r\n\r\n def _close_line(self, line):\r\n x, y = line.get_data()\r\n # FIXME: markers at x[0], y[0] get doubled-up\r\n if x[0] != x[-1]:\r\n x = np.append(x, x[0])\r\n y = np.append(y, y[0])\r\n line.set_data(x, y)\r\n\r\n def set_varlabels(self, labels):\r\n self.set_thetagrids(np.degrees(theta), labels)\r\n\r\n def _gen_axes_patch(self):\r\n # The Axes patch must be centered at (0.5, 0.5) and of radius 0.5\r\n # in axes coordinates.\r\n if frame == 'circle':\r\n return Circle((0.5, 0.5), 0.5)\r\n elif frame == 'polygon':\r\n return RegularPolygon((0.5, 0.5), num_vars,\r\n radius=.5, edgecolor=\"k\")\r\n else:\r\n raise ValueError(\"Unknown value for 'frame': %s\" % frame)\r\n\r\n def _gen_axes_spines(self):\r\n if frame == 'circle':\r\n return super()._gen_axes_spines()\r\n elif frame == 'polygon':\r\n # spine_type must be 'left'/'right'/'top'/'bottom'/'circle'.\r\n spine = Spine(axes=self,\r\n spine_type='circle',\r\n path=Path.unit_regular_polygon(num_vars))\r\n # unit_regular_polygon gives a polygon of radius 1 centered at\r\n # (0, 0) but we want a polygon of radius 0.5 centered at (0.5,\r\n # 0.5) in axes coordinates.\r\n spine.set_transform(Affine2D().scale(.5).translate(.5, .5)\r\n + self.transAxes)\r\n return {'polar': spine}\r\n else:\r\n raise ValueError(\"Unknown value for 'frame': %s\" % frame)\r\n\r\n def draw(self, renderer, *args, **kwargs):\r\n \"\"\" Draw. If frame is polygon, make gridlines polygon-shaped \"\"\"\r\n if frame == 'polygon':\r\n gridlines = self.yaxis.get_gridlines()\r\n print(self.get_yaxis().get_gridlines())\r\n for gl in gridlines:\r\n gl.get_path()._interpolation_steps = num_vars\r\n super().draw(renderer, *args, **kwargs)\r\n\r\n register_projection(RadarAxes)\r\n return theta\r\n\r\n\r\ndef example_data():\r\n # The following data is from the Denver Aerosol Sources and Health study.\r\n # See doi:10.1016/j.atmosenv.2008.12.017\r\n #\r\n # The data are pollution source profile estimates for five modeled\r\n # pollution sources (e.g., cars, wood-burning, etc) that emit 7-9 chemical\r\n # species. The radar charts are experimented with here to see if we can\r\n # nicely visualize how the modeled source profiles change across four\r\n # scenarios:\r\n # 1) No gas-phase species present, just seven particulate counts on\r\n # Sulfate\r\n # Nitrate\r\n # Elemental Carbon (EC)\r\n # Organic Carbon fraction 1 (OC)\r\n # Organic Carbon fraction 2 (OC2)\r\n # Organic Carbon fraction 3 (OC3)\r\n # Pyrolized Organic Carbon (OP)\r\n # 2)Inclusion of gas-phase specie carbon monoxide (CO)\r\n # 3)Inclusion of gas-phase specie ozone (O3).\r\n # 4)Inclusion of both gas-phase species is present...\r\n data = [\r\n ['Sulfate', 'Nitrate', 'EC', 'OC1', 'OC2', 'OC3', 'OP', 'CO', 'O3'],\r\n ('Basecase', [\r\n [0.88, 0.01, 0.03, 0.03, 0.00, 0.06, 0.01, 0.00, 0.00],\r\n [0.07, 0.95, 0.04, 0.05, 0.00, 0.02, 0.01, 0.00, 0.00],\r\n [0.01, 0.02, 0.85, 0.19, 0.05, 0.10, 0.00, 0.00, 0.00],\r\n [0.02, 0.01, 0.07, 0.01, 0.21, 0.12, 0.98, 0.00, 0.00],\r\n [0.01, 0.01, 0.02, 0.71, 0.74, 0.70, 0.00, 0.00, 0.00]]),\r\n ('With CO', [\r\n [0.88, 0.02, 0.02, 0.02, 0.00, 0.05, 0.00, 0.05, 0.00],\r\n [0.08, 0.94, 0.04, 0.02, 0.00, 0.01, 0.12, 0.04, 0.00],\r\n [0.01, 0.01, 0.79, 0.10, 0.00, 0.05, 0.00, 0.31, 0.00],\r\n [0.00, 0.02, 0.03, 0.38, 0.31, 0.31, 0.00, 0.59, 0.00],\r\n [0.02, 0.02, 0.11, 0.47, 0.69, 0.58, 0.88, 0.00, 0.00]]),\r\n ('With O3', [\r\n [0.89, 0.01, 0.07, 0.00, 0.00, 0.05, 0.00, 0.00, 0.03],\r\n [0.07, 0.95, 0.05, 0.04, 0.00, 0.02, 0.12, 0.00, 0.00],\r\n [0.01, 0.02, 0.86, 0.27, 0.16, 0.19, 0.00, 0.00, 0.00],\r\n [0.01, 0.03, 0.00, 0.32, 0.29, 0.27, 0.00, 0.00, 0.95],\r\n [0.02, 0.00, 0.03, 0.37, 0.56, 0.47, 0.87, 0.00, 0.00]]),\r\n ('CO \u0026 O3', [\r\n [0.87, 0.01, 0.08, 0.00, 0.00, 0.04, 0.00, 0.00, 0.01],\r\n [0.09, 0.95, 0.02, 0.03, 0.00, 0.01, 0.13, 0.06, 0.00],\r\n [0.01, 0.02, 0.71, 0.24, 0.13, 0.16, 0.00, 0.50, 0.00],\r\n [0.01, 0.03, 0.00, 0.28, 0.24, 0.23, 0.00, 0.44, 0.88],\r\n [0.02, 0.00, 0.18, 0.45, 0.64, 0.55, 0.86, 0.00, 0.16]])\r\n ]\r\n return data\r\n\r\n\r\nif __name__ == '__main__':\r\n N = 9\r\n theta = radar_factory(N, frame='polygon')\r\n\r\n data = example_data()\r\n spoke_labels = data.pop(0)\r\n\r\n fig, axs = plt.subplots(figsize=(9, 9), nrows=2, ncols=2,\r\n subplot_kw=dict(projection='radar'))\r\n fig.subplots_adjust(wspace=0.25, hspace=0.20, top=0.85, bottom=0.05)\r\n\r\n colors = ['b', 'r', 'g', 'm', 'y']\r\n # Plot the four cases from the example data on separate axes\r\n for ax, (title, case_data) in zip(axs.flat, data):\r\n ax.set_rgrids([0.2, 0.4, 0.6, 0.8])\r\n ax.set_title(title, weight='bold', size='medium', position=(0.5, 1.1),\r\n horizontalalignment='center', verticalalignment='center')\r\n for d, color in zip(case_data, colors):\r\n ax.plot(theta, d, color=color)\r\n ax.fill(theta, d, facecolor=color, alpha=0.25)\r\n ax.set_varlabels(spoke_labels)\r\n\r\n # add legend relative to top-left plot\r\n labels = ('Factor 1', 'Factor 2', 'Factor 3', 'Factor 4', 'Factor 5')\r\n legend = axs[0, 0].legend(labels, loc=(0.9, .95),\r\n labelspacing=0.1, fontsize='small')\r\n\r\n fig.text(0.5, 0.965, '5-Factor Solution Profiles Across Four Scenarios',\r\n horizontalalignment='center', color='black', weight='bold',\r\n size='large')\r\n\r\n plt.show()\r\n```\r\n\r\n**Actual outcome**\r\n\r\n\u003c!--The output produced by the above code, which may be a screenshot, console output, etc.--\u003e\r\n\r\n\r\n**Expected outcome**\r\n\r\n\u003c!--A description of the expected outcome from the code snippet--\u003e\r\n\u003c!--If this used to work in an earlier version of Matplotlib, please note the version it used to work on--\u003e\r\nIt used to work in older versions, like in 3.2.1. But it stopped working in 3.3.0.\r\n\r\n\r\n**Matplotlib version**\r\n\u003c!--Please specify your platform and versions of the relevant libraries you are using:--\u003e\r\n * Operating system: Ubuntu 20.04\r\n * Matplotlib version (`import matplotlib; print(matplotlib.__version__)`): 3.4.1\r\n * Matplotlib backend (`print(matplotlib.get_backend())`): backend_interagg\r\n * Python version: 3.8.5\r\n * Jupyter version (if applicable): NA\r\n * Other libraries: numpy 1.20.2\r\n\r\n\u003c!--Please tell us how you installed matplotlib and python e.g., from source, pip, conda--\u003e\r\n\u003c!--If you installed from conda, please specify which channel you used if not the default--\u003e\r\nPython was installed via the package manager of Ubuntu. matplotlib via pip3.\r\n","author":{"url":"https://github.com/prohde","@type":"Person","name":"prohde"},"datePublished":"2021-04-16T12:40:57.000Z","interactionStatistic":{"@type":"InteractionCounter","interactionType":"https://schema.org/CommentAction","userInteractionCount":7},"url":"https://github.com/19981/matplotlib/issues/19981"}
| 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:6e35056b-8df3-b82a-6e2c-d44171af27dc |
| current-catalog-service-hash | 81bb79d38c15960b92d99bca9288a9108c7a47b18f2423d0f6438c5b7bcd2114 |
| request-id | 88C8:2B78D3:6945A2:8B9A7E:6A5307B8 |
| html-safe-nonce | 7bf46533e6d44ac01751e45b618c3f8ec496c4b629479346669b26c411670a9c |
| visitor-payload | eyJyZWZlcnJlciI6IiIsInJlcXVlc3RfaWQiOiI4OEM4OjJCNzhEMzo2OTQ1QTI6OEI5QTdFOjZBNTMwN0I4IiwidmlzaXRvcl9pZCI6IjQ3OTM0Nzg4MDg4OTEyMzAxMzYiLCJyZWdpb25fZWRnZSI6ImlhZCIsInJlZ2lvbl9yZW5kZXIiOiJpYWQifQ== |
| visitor-hmac | 8dbd7b1964c163baeebf03896b6a191dbcceae64742977b14c0b72c7c6a50554 |
| hovercard-subject-tag | issue:859778325 |
| 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/19981/issue_layout |
| twitter:image | https://opengraph.githubassets.com/74d02972ead49362c789aef685dcaf43c8c49e4442fa4e9365e27732feaf5b77/matplotlib/matplotlib/issues/19981 |
| twitter:card | summary_large_image |
| og:image | https://opengraph.githubassets.com/74d02972ead49362c789aef685dcaf43c8c49e4442fa4e9365e27732feaf5b77/matplotlib/matplotlib/issues/19981 |
| og:image:alt | Bug report Bug summary I was able to create radar charts with polygonal grid lines before. But the code is now producing circular grid lines. It was working in version 3.2.x but since 3.3.0 the gri... |
| og:image:width | 1200 |
| og:image:height | 600 |
| og:site_name | GitHub |
| og:type | object |
| og:author:username | prohde |
| 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 | 07a982c1d40157c619b364352b704c3ce66bb332 |
| ui-target | full |
| theme-color | #1e2327 |
| color-scheme | light dark |
Links:
Viewport: width=device-width