pythonmatplotlibcharts

Polar Bar Charts with Color maps in Python


I am trying to create a polar chart that has four categories. Each category has two values: sleep_time and ahi. I am wanting the size of each bar to be proportional to the sleep_time - which seems to be working. I also want the color to be based on the ahi that is also associated with each category. Then have a color bar to reflect this. I can get the sleep_time function going but my color is the issue. This is what I have so far:

import matplotlib.pyplot as plt
import numpy as np

categories = ['Right', 'Supine', 'Left', 'Prone']
sleep_time = [251.5, 40, 130, 15.5]
ahi = [12.5, 65.6, 8.2, 0.0]


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

fig, ax = plt.subplots(figsize=(8, 8), subplot_kw=dict(projection='polar'))

colors = plt.cm.viridis_r(np.linspace(0, 100, len(ahi)))

ax.bar(angles, sleep_time, width=1.0, align='center', alpha=0.5)
ax.bar(angles, ahi, width=0.4, align='edge', alpha=0.5, color=colors)

ax.set_xticks(angles)
ax.set_xticklabels(categories)

colorbar = plt.colorbar(ahi)
colorbar.set_ticks([0, 30, 60, 90, 120, 150, 180])

plt.show()

plt.savefig('position_vs._ahi.png')

Solution

  • You were nearly there. Just change the way you create your colors from ahi. Also no need to add 2 bar, you can add the values in ahi directly as the color= argument in ax.bar. Then adding a Mappable to get your colorbar in accordance with ahi:

    import matplotlib.pyplot as plt
    import numpy as np
    from matplotlib.cm import ScalarMappable
    from matplotlib.colors import Normalize
    
    categories = ['Right', 'Supine', 'Left', 'Prone']
    sleep_time = [251.5, 40, 130, 15.5]
    ahi = [12.5, 65.6, 8.2, 0.0]
    
    angles = np.linspace(0, 2*np.pi, len(categories), endpoint=False)
    
    fig = plt.figure(figsize=(10, 8))
    ax = fig.add_subplot(111, projection='polar')
    
    norm = Normalize(vmin=min(ahi), vmax=max(ahi))
    cmap = plt.cm.viridis_r
    colors = cmap(norm(ahi))
    
    bars = ax.bar(angles, sleep_time, width=0.8, align='center', alpha=0.7, color=colors)
    
    ax.set_xticks(angles)
    ax.set_xticklabels(categories)
    
    sm = ScalarMappable(norm=norm, cmap=cmap)
    sm.set_array([])
    colorbar = fig.colorbar(sm, ax=ax)  
    colorbar.set_label('AHI Value', rotation=270, labelpad=15)
    
    plt.tight_layout()
    plt.show()