Search code examples
pythonmatplotlibpie-chartcolor-schemepolar-coordinates

Coloring a polar bar chart with hue color without discontinuity at 0


I need to color a circular histogram with color that corresponds to the angle.

I found an example in matplotlib library that colors a polar scatterplot in the way that I need: https://matplotlib.org/examples/pie_and_polar_charts/polar_scatter_demo.html

But this is a scatterplot, and I need a circular histogram, and I use the code from the response to this question: Circular Histogram for Python

I want to be able to change so that the bars have the colors from the first image. But the ax.bar doesn't take a string color as a scatterplot does, returning an error.

Here is the code for the circular histogram:

import numpy as np
import matplotlib.pyplot as plt 

N = 80
bottom = 8
max_height = 4

theta = np.linspace(0.0, 2 * np.pi, N, endpoint=False)
radii = max_height*np.random.rand(N)
width = (2*np.pi) / N

ax = plt.subplot(111, polar=True)
bars = ax.bar(theta, radii, width=width, bottom=bottom)

# Use custom colors and opacity
for r, bar in zip(radii, bars):
    bar.set_facecolor(plt.cm.jet(r / 10.))
    bar.set_alpha(0.8)

plt.show()

Edit: substituting radii for theta in the last part of the plot changes the colors of the bars, but doesn't produce the color scheme in which the colors change continuously over the whole range of the circle. I tried normalising theta in degrees and radians as proposed in the comments:

bar.set_facecolor(math.degrees(r)/360))

and

bar.set_facecolor(plt.cm.jet(r/2*np.pi))

Both of which produce the wrong solution.


Solution

  • It looks like the example would need some overhaul. It can be simplified as follows, where the two requested changes from the question are:

    1. Use a different colormap (here hsv).
    2. Encode the angle (theta) instead of the radius (radii) into color.

    No loop is needed for that.

    import numpy as np
    import matplotlib.pyplot as plt
    
    # Fixing random state for reproducibility
    np.random.seed(19680801)
    
    # Compute pie slices
    N = 20
    theta = np.linspace(0.0, 2 * np.pi, N, endpoint=False)
    radii = 10 * np.random.rand(N)
    width = 2 * np.pi / N
    colors = plt.cm.hsv(theta/2/np.pi)
    
    ax = plt.subplot(111, projection='polar')
    bars = ax.bar(theta, radii, width=width, bottom=4, color=colors)
    
    plt.show()
    

    enter image description here