famargar
famargar

Reputation: 3428

Create a circular barplot in python

I would be interested in using a circular barplot visualisation for my project, and have no idea whatsoever how to produce it in Python. Please see an example of what I mean for "circular barplot" below. Data would come in form of a pandas series - dummy example below to vaguely reflect the plot:

A 33
B 62
C 56
D 70

Any idea?

here, using R

Upvotes: 8

Views: 11574

Answers (3)

Mr. T
Mr. T

Reputation: 12410

You could also make use of the dismissed donut plot:

import matplotlib.pyplot as plt
from matplotlib import cm
from math import log10

labels = list("ABCDEFG")
data = [21, 57, 88, 14, 76, 91, 26]
#number of data points
n = len(data)
#find max value for full ring
k = 10 ** int(log10(max(data)))
m = k * (1 + max(data) // k)

#radius of donut chart
r = 1.5
#calculate width of each ring
w = r / n 

#create colors along a chosen colormap
colors = [cm.terrain(i / n) for i in range(n)]

#create figure, axis
fig, ax = plt.subplots()
ax.axis("equal")

#create rings of donut chart
for i in range(n):
    #hide labels in segments with textprops: alpha = 0 - transparent, alpha = 1 - visible
    innerring, _ = ax.pie([m - data[i], data[i]], radius = r - i * w, startangle = 90, labels = ["", labels[i]], labeldistance = 1 - 1 / (1.5 * (n - i)), textprops = {"alpha": 0}, colors = ["white", colors[i]])
    plt.setp(innerring, width = w, edgecolor = "white")

plt.legend()
plt.show()

Output:

enter image description here

Upvotes: 9

Stop harming Monica
Stop harming Monica

Reputation: 12590

That is just an horizontal bar plot in polar projection. Matplotlib defaults will make it look a bit different.

ax = plt.subplot(projection='polar')
ax.barh(0, math.radians(150))
ax.barh(1, math.radians(300))
ax.barh(2, math.radians(270))
ax.barh(3, math.radians(320))

enter image description here

But it can be tuned:

  • Use set_theta_zero_location() to make the bars start at North.
  • Use set_theta_direction() to make the bars go clockwise.
  • Use set_rlabel_position() to move the radial labels.
  • Use set_thetagrids() and set_rgrids() to set the ticks and labels.

The result is very similar:

ax.set_theta_zero_location('N')
ax.set_theta_direction(-1)
ax.set_rlabel_position(0)
ax.set_thetagrids([0, 96, 192, 288], labels=[0, 20, 40, 60])
ax.set_rgrids([0, 1, 2, 3], labels=['a', 'b', 'c', 'd'])

enter image description here

There must be a way to move the radial labels to the left of the bars but I could not find it.

PS A more concise and maybe faster way:

ax.barh([0, 1, 2, 3], np.radians([150, 300, 270, 320]),
        color=plt.rcParams['axes.prop_cycle'].by_key()['color'])

Upvotes: 8

Guybrush
Guybrush

Reputation: 2780

This can be done with matplotlib. The trick is to draw barplots in polar coordinates. Have a look at this example, taken from matplotlib documentation: https://matplotlib.org/1.2.1/examples/pylab_examples/polar_bar.html

Other kinds of "circular bar plots" can be made based on these examples: https://python-graph-gallery.com/donut-plot/

More info on https://datavizcatalogue.com/methods/donut_chart.html

However, I don't know a direct way to get what you're looking for using matplotlib.

Upvotes: 1

Related Questions