Techno Blender
Digitally Yours.

Enhance Your Polar Bar Charts With Matplotlib | by Andy McDonald | Apr, 2023

0 33


Polar bar chart created with matplotlib and themed using mplcyberpunk. Image by the author.

Polar bar charts provide a great alternative to traditional bar charts. Rather than the bars being arranged horizontally or vertically on Cartesian coordinates, these charts represent them using a polar grid.

Plotting data this way can help visualise cyclical data and provide a more eye-catching and aesthetically pleasing data visualisation.

Polar bar charts can easily be created in matplotlib; however, the default chart is lacking and needs a little work to make it more visually appealing.

Within this short tutorial, we will see how we can improve upon the basic chart that is generated by changing the styling and even applying a cyberpunk theme to the data for something more eye-catching.

The first step is to import the libraries that we will need. In this tutorial, we will be using numpy to perform some calculations and matplotlib to display our plot.

import numpy as np
import matplotlib.pyplot as plt

Once the libraries have been imported, we can create some data to work with.

For this example, we will create dummy data representing a survey where people select their favourite rock type.

To create this dummy data set, we first have to create ten random integers between 1 and 10. This will represent ten different rock names, which we will create next and assign to the variable rock_names.

rankings = np.random.randint(1, 10, 10)

rock_names = [
'Granite',
'Basalt',
'Gneiss',
'Schist',
'Sandstone',
'Limestone',
'Shale',
'Conglomerate',
'Dolomite',
'Marble'
]

Creating simple charts is very easy with matplotlib.

Let’s create a simple bar chart to see what our plot would look like.

To create the bar chart, all we need are two lines of code.

plt.bar(x=rock_names, height=rankings)
plt.show()

When the code is run, we get the following chart.

Basic bar chart created using matplotlib. Image by the author.

This is the standard chart style that is generated using matplotlib. They are very dull, uninspiring, and often confusing. Generally, we need to improve these charts with several lines of code before we have something that can be used in a infographic or visualisation dashboard.

In a previous article, I covered how to take your traditional bar chart to the next level in 7 simple steps. You can check it out below.

Let’s now have a look at a polar bar chart, which is essentially the same chart as above, but rather than being plotted on a traditional cartesian coordinate system; we are now plotting it on a polar project.

As you can see below, we need several lines of code to create our basic figure.

fig, ax = plt.subplots(subplot_kw={'projection': 'polar'}, figsize=(10,10))

indexes = list(range(0, len(rock_names)))
width = 2*np.pi / len(rock_names)
angles = [element * width for element in indexes]

label_loc = np.linspace(start=0, stop=2 * np.pi, num=len(rock_names))

bars = ax.bar(x = angles, height=rankings, width=width,
edgecolor='black', zorder=2, alpha=0.8)

plt.show()

First, we need to create our figure object by calling upon plt.subplots. It is here that we can specify that we want the data to be plotted on a polar projection.

We then create four new variables based on our original lists:

  • indexes : creates a list of numbers ranging from 0 to the total number of items in our list. In our case, this will generate a list from 0 to 9.
  • width : creates a list based on calculating the width of each bar in the chart by dividing the circumference of a circle by the number of rock types we have in rock_names
  • angles : creates a list containing the angles for each of the rock types
  • label_loc : creates a list of evenly spaced values between 0 and 2 * pi for displaying the rock-type labels

Once these variables have been created, we can call upon ax.bar and begin passing in some of the variables to the required parameters.

To make the grid appear below the bars, we can set the zorder value to 2.

We will also set the edgecolour of the bars to black and the opacity (alpha) to 0.8.

When we run the code, we return the following chart, and we now have a basic polar bar plot.

A basic matplotlib polar bar chart. Image by the author.

In the above chart, we can see that we do not know what each of the bars are — which can be addressed by adding our labels from the label_loc list.

We will also see that the spokes extending from the centre do not match the bars, which we can easily address.

Adding Labels to the Polar Bar Chart

First, let’s add some labels to our plot.

To ensure our labels are easily readable without having to strain our necks, we can make sure that the labels are positioned appropriately.

To do this, we need to loop over the elements in our angles , rankings and rock_names lists.

We then need to convert the angle measurement from radians to degrees.

We then need to check what the current angle is within the loop. If the angle of the bar is less than pi, then 90 degrees is subtracted from the rotation angle. Otherwise, if the bar is in the bottom half of the circle, 90 degrees is added to the rotation angle.

Note that in the previous image, 0 degrees is located on the right-hand side of the plot.

Following that, we then need to add the labels using ax.text. To ensure that the labels are positioned outside the plot, we can set the y parameter to 11, as our max value for our outer ring is 10.

fig, ax = plt.subplots(subplot_kw={'projection': 'polar'}, figsize=(10,10))

indexes = list(range(0, len(rock_names)))
width = 2*np.pi / len(rock_names)
angles = [element * width for element in indexes]

label_loc = np.linspace(start=0, stop=2 * np.pi, num=len(rock_names))

bars = ax.bar(x = angles, height=rankings, width=width,
edgecolor='black', zorder=2, alpha=0.8)

for angle, height, rock_name in zip(angles, rankings, rock_names):
rotation_angle = np.degrees(angle)
if angle < np.pi:
rotation_angle -= 90
elif angle == np.pi:
rotation_angle -= 90
else:
rotation_angle += 90
ax.text(angle, 11, rock_name,
ha='center', va='center',
rotation=rotation_angle, rotation_mode='anchor', fontsize=16)

plt.show()

When the code is run, we now get the following plot with the labels neatly positioned around the chart, and they are easily readable.

Polar bar chart after setting the labels to be parallel with the bars. Image by the author.

In the previous plots, we had the grid displayed in the background. However, the spokes are misaligned with the edges of the bars.

There are a few ways to tackle this. In this example, I have added a second radial bar chart which sits underneath the data bars called bars_bg . This is set to grey, and the height parameter is set to 10, which creates a fill all the way to the edge of the plot.

bars_bg = ax.bar(x = angles, height=10, width=width, color='lightgrey',
edgecolor='white', zorder=1, alpha=0.8)

To hide the grid lines, we can use ax.set_ticks and pass it an empty list.

We may also want to retain the polar grid so that we can see the segments clearly. This is optional, but it can help with readability.

ax.set_xticks([])

ax.grid(alpha=0.8, color='white', lw=3)

Our full code for creating the polar bar chart now looks like this:

fig, ax = plt.subplots(subplot_kw={'projection': 'polar'}, figsize=(10,10))

indexes = list(range(0, len(rock_names)))
width = 2*np.pi / len(rock_names)
angles = [element * width for element in indexes]

label_loc = np.linspace(start=0, stop=2 * np.pi, num=len(rock_names))

bars_bg = ax.bar(x = angles, height=10, width=width, color='lightgrey',
edgecolor='white', zorder=1, alpha=0.8)

bars = ax.bar(x = angles, height=rankings, width=width,
edgecolor='white', zorder=1, alpha=0.8)

for angle, height, rock_name in zip(angles, rankings, rock_names):
rotation_angle = np.degrees(angle)
if angle < np.pi:
rotation_angle -= 90
elif angle == np.pi:
rotation_angle -= 90
else:
rotation_angle += 90
ax.text(angle, 11, rock_name,
ha='center', va='center',
rotation=rotation_angle, rotation_mode='anchor', fontsize=16)

ax.set_xticks([])

ax.grid(alpha=0.8, color='white', lw=3)

plt.ylim(0, 10)
plt.show()

Which then generates the following plot.

Polar bar chart after tweaking styling and fixing gridlines. Image by the author.

We can tweak the plot until we are happy with it, however, this gives a much more improved plot compared to the one we started with.

If we want to change the styling of the plot, we can use one of the many theming libraries available for matplotlib.

Applying these styles often requires adding a couple of lines of code — usually an import statement and a with statement containing the selected style.

Here is the full code for cyberpunking the plot. Note that a few changes were made to the to alpha values for the bars to make them slightly less “in your face”.

import mplcyberpunk

with plt.style.context('cyberpunk'):
fig, ax = plt.subplots(subplot_kw={'projection': 'polar'}, figsize=(10,10))

angles = np.linspace(0, 2*np.pi, len(rock_names), endpoint=False)

indexes = list(range(0, len(rock_names)))
width = 2*np.pi / len(rock_names)
angles = [element * width for element in indexes]

label_loc = np.linspace(start=0, stop=2 * np.pi, num=len(rock_names))
bars_bg = ax.bar(x = angles, height=10, width=width, color='lightgrey',
edgecolor='white', zorder=1, alpha=0.05)

bars = ax.bar(x = angles, height=rankings, width=width,
edgecolor='white', zorder=2, alpha=0.6)

for angle, height, rock_name in zip(angles, rankings, rock_names):
rotation_angle = np.degrees(angle)
if angle < np.pi:
rotation_angle -= 90
elif angle == np.pi:
rotation_angle -= 90
else:
rotation_angle += 90
ax.text(angle, 11, rock_name,
ha='center', va='center',
rotation=rotation_angle, rotation_mode='anchor', fontsize=16)

ax.set_xticks([])

ax.grid(alpha=0.1, color='white', lw=3)

plt.ylim(0, 10)

plt.show()

After running the above code, we get back the following figure, which is great for including in infographics and for catching people’s attention.

Polar bar chart after applying cyberpunk theming. Image by the author.

To learn more about other styling libraries, check out my article below on four essential ones that will take your matplotlib figures to the next level.

Polar bar charts provide a great alternative to the traditional bar chart by representing the data on a polar grid rather. This can be helpful when looking at cyclical data and creating visually appealing data visualisation.

As matplotlib is known for creating boring and bland plots out of the box, we can — with a few tweaks and several lines of code — make them look significantly better.

The numerous themes available for matplotlib also allow us to go from a basic plot to something completely different with a few additional lines of code.


Polar bar chart created with matplotlib and themed using mplcyberpunk. Image by the author.

Polar bar charts provide a great alternative to traditional bar charts. Rather than the bars being arranged horizontally or vertically on Cartesian coordinates, these charts represent them using a polar grid.

Plotting data this way can help visualise cyclical data and provide a more eye-catching and aesthetically pleasing data visualisation.

Polar bar charts can easily be created in matplotlib; however, the default chart is lacking and needs a little work to make it more visually appealing.

Within this short tutorial, we will see how we can improve upon the basic chart that is generated by changing the styling and even applying a cyberpunk theme to the data for something more eye-catching.

The first step is to import the libraries that we will need. In this tutorial, we will be using numpy to perform some calculations and matplotlib to display our plot.

import numpy as np
import matplotlib.pyplot as plt

Once the libraries have been imported, we can create some data to work with.

For this example, we will create dummy data representing a survey where people select their favourite rock type.

To create this dummy data set, we first have to create ten random integers between 1 and 10. This will represent ten different rock names, which we will create next and assign to the variable rock_names.

rankings = np.random.randint(1, 10, 10)

rock_names = [
'Granite',
'Basalt',
'Gneiss',
'Schist',
'Sandstone',
'Limestone',
'Shale',
'Conglomerate',
'Dolomite',
'Marble'
]

Creating simple charts is very easy with matplotlib.

Let’s create a simple bar chart to see what our plot would look like.

To create the bar chart, all we need are two lines of code.

plt.bar(x=rock_names, height=rankings)
plt.show()

When the code is run, we get the following chart.

Basic bar chart created using matplotlib. Image by the author.

This is the standard chart style that is generated using matplotlib. They are very dull, uninspiring, and often confusing. Generally, we need to improve these charts with several lines of code before we have something that can be used in a infographic or visualisation dashboard.

In a previous article, I covered how to take your traditional bar chart to the next level in 7 simple steps. You can check it out below.

Let’s now have a look at a polar bar chart, which is essentially the same chart as above, but rather than being plotted on a traditional cartesian coordinate system; we are now plotting it on a polar project.

As you can see below, we need several lines of code to create our basic figure.

fig, ax = plt.subplots(subplot_kw={'projection': 'polar'}, figsize=(10,10))

indexes = list(range(0, len(rock_names)))
width = 2*np.pi / len(rock_names)
angles = [element * width for element in indexes]

label_loc = np.linspace(start=0, stop=2 * np.pi, num=len(rock_names))

bars = ax.bar(x = angles, height=rankings, width=width,
edgecolor='black', zorder=2, alpha=0.8)

plt.show()

First, we need to create our figure object by calling upon plt.subplots. It is here that we can specify that we want the data to be plotted on a polar projection.

We then create four new variables based on our original lists:

  • indexes : creates a list of numbers ranging from 0 to the total number of items in our list. In our case, this will generate a list from 0 to 9.
  • width : creates a list based on calculating the width of each bar in the chart by dividing the circumference of a circle by the number of rock types we have in rock_names
  • angles : creates a list containing the angles for each of the rock types
  • label_loc : creates a list of evenly spaced values between 0 and 2 * pi for displaying the rock-type labels

Once these variables have been created, we can call upon ax.bar and begin passing in some of the variables to the required parameters.

To make the grid appear below the bars, we can set the zorder value to 2.

We will also set the edgecolour of the bars to black and the opacity (alpha) to 0.8.

When we run the code, we return the following chart, and we now have a basic polar bar plot.

A basic matplotlib polar bar chart. Image by the author.

In the above chart, we can see that we do not know what each of the bars are — which can be addressed by adding our labels from the label_loc list.

We will also see that the spokes extending from the centre do not match the bars, which we can easily address.

Adding Labels to the Polar Bar Chart

First, let’s add some labels to our plot.

To ensure our labels are easily readable without having to strain our necks, we can make sure that the labels are positioned appropriately.

To do this, we need to loop over the elements in our angles , rankings and rock_names lists.

We then need to convert the angle measurement from radians to degrees.

We then need to check what the current angle is within the loop. If the angle of the bar is less than pi, then 90 degrees is subtracted from the rotation angle. Otherwise, if the bar is in the bottom half of the circle, 90 degrees is added to the rotation angle.

Note that in the previous image, 0 degrees is located on the right-hand side of the plot.

Following that, we then need to add the labels using ax.text. To ensure that the labels are positioned outside the plot, we can set the y parameter to 11, as our max value for our outer ring is 10.

fig, ax = plt.subplots(subplot_kw={'projection': 'polar'}, figsize=(10,10))

indexes = list(range(0, len(rock_names)))
width = 2*np.pi / len(rock_names)
angles = [element * width for element in indexes]

label_loc = np.linspace(start=0, stop=2 * np.pi, num=len(rock_names))

bars = ax.bar(x = angles, height=rankings, width=width,
edgecolor='black', zorder=2, alpha=0.8)

for angle, height, rock_name in zip(angles, rankings, rock_names):
rotation_angle = np.degrees(angle)
if angle < np.pi:
rotation_angle -= 90
elif angle == np.pi:
rotation_angle -= 90
else:
rotation_angle += 90
ax.text(angle, 11, rock_name,
ha='center', va='center',
rotation=rotation_angle, rotation_mode='anchor', fontsize=16)

plt.show()

When the code is run, we now get the following plot with the labels neatly positioned around the chart, and they are easily readable.

Polar bar chart after setting the labels to be parallel with the bars. Image by the author.

In the previous plots, we had the grid displayed in the background. However, the spokes are misaligned with the edges of the bars.

There are a few ways to tackle this. In this example, I have added a second radial bar chart which sits underneath the data bars called bars_bg . This is set to grey, and the height parameter is set to 10, which creates a fill all the way to the edge of the plot.

bars_bg = ax.bar(x = angles, height=10, width=width, color='lightgrey',
edgecolor='white', zorder=1, alpha=0.8)

To hide the grid lines, we can use ax.set_ticks and pass it an empty list.

We may also want to retain the polar grid so that we can see the segments clearly. This is optional, but it can help with readability.

ax.set_xticks([])

ax.grid(alpha=0.8, color='white', lw=3)

Our full code for creating the polar bar chart now looks like this:

fig, ax = plt.subplots(subplot_kw={'projection': 'polar'}, figsize=(10,10))

indexes = list(range(0, len(rock_names)))
width = 2*np.pi / len(rock_names)
angles = [element * width for element in indexes]

label_loc = np.linspace(start=0, stop=2 * np.pi, num=len(rock_names))

bars_bg = ax.bar(x = angles, height=10, width=width, color='lightgrey',
edgecolor='white', zorder=1, alpha=0.8)

bars = ax.bar(x = angles, height=rankings, width=width,
edgecolor='white', zorder=1, alpha=0.8)

for angle, height, rock_name in zip(angles, rankings, rock_names):
rotation_angle = np.degrees(angle)
if angle < np.pi:
rotation_angle -= 90
elif angle == np.pi:
rotation_angle -= 90
else:
rotation_angle += 90
ax.text(angle, 11, rock_name,
ha='center', va='center',
rotation=rotation_angle, rotation_mode='anchor', fontsize=16)

ax.set_xticks([])

ax.grid(alpha=0.8, color='white', lw=3)

plt.ylim(0, 10)
plt.show()

Which then generates the following plot.

Polar bar chart after tweaking styling and fixing gridlines. Image by the author.

We can tweak the plot until we are happy with it, however, this gives a much more improved plot compared to the one we started with.

If we want to change the styling of the plot, we can use one of the many theming libraries available for matplotlib.

Applying these styles often requires adding a couple of lines of code — usually an import statement and a with statement containing the selected style.

Here is the full code for cyberpunking the plot. Note that a few changes were made to the to alpha values for the bars to make them slightly less “in your face”.

import mplcyberpunk

with plt.style.context('cyberpunk'):
fig, ax = plt.subplots(subplot_kw={'projection': 'polar'}, figsize=(10,10))

angles = np.linspace(0, 2*np.pi, len(rock_names), endpoint=False)

indexes = list(range(0, len(rock_names)))
width = 2*np.pi / len(rock_names)
angles = [element * width for element in indexes]

label_loc = np.linspace(start=0, stop=2 * np.pi, num=len(rock_names))
bars_bg = ax.bar(x = angles, height=10, width=width, color='lightgrey',
edgecolor='white', zorder=1, alpha=0.05)

bars = ax.bar(x = angles, height=rankings, width=width,
edgecolor='white', zorder=2, alpha=0.6)

for angle, height, rock_name in zip(angles, rankings, rock_names):
rotation_angle = np.degrees(angle)
if angle < np.pi:
rotation_angle -= 90
elif angle == np.pi:
rotation_angle -= 90
else:
rotation_angle += 90
ax.text(angle, 11, rock_name,
ha='center', va='center',
rotation=rotation_angle, rotation_mode='anchor', fontsize=16)

ax.set_xticks([])

ax.grid(alpha=0.1, color='white', lw=3)

plt.ylim(0, 10)

plt.show()

After running the above code, we get back the following figure, which is great for including in infographics and for catching people’s attention.

Polar bar chart after applying cyberpunk theming. Image by the author.

To learn more about other styling libraries, check out my article below on four essential ones that will take your matplotlib figures to the next level.

Polar bar charts provide a great alternative to the traditional bar chart by representing the data on a polar grid rather. This can be helpful when looking at cyclical data and creating visually appealing data visualisation.

As matplotlib is known for creating boring and bland plots out of the box, we can — with a few tweaks and several lines of code — make them look significantly better.

The numerous themes available for matplotlib also allow us to go from a basic plot to something completely different with a few additional lines of code.

FOLLOW US ON GOOGLE NEWS

Read original article here

Denial of responsibility! Techno Blender is an automatic aggregator of the all world’s media. In each content, the hyperlink to the primary source is specified. All trademarks belong to their rightful owners, all materials to their authors. If you are the owner of the content and do not want us to publish your materials, please contact us by email – [email protected]. The content will be deleted within 24 hours.

Leave a comment