Search code examples
pythongraphcolormap3d-mapping

How to colour a variable on basis of highest and lowest or at some cut off value for 3d Bar graph in python


I want to give different gradient colour for z i.e Numeric variable in my 3D Bar Graph on the basis of some cut of value or gradient for lowest to highest value.I want to put condition say if dz is >=50 then green colour bar else red colour ba. Attached the code, Please share if there's any solution for this.

from mpl_toolkits.mplot3d import Axes3D
import matplotlib.pyplot as plt
import numpy as np

fig = plt.figure()
ax = fig.add_subplot(111, projection = "3d")

ax.set_xlabel("Cumulative HH's")
ax.set_ylabel("Index") 
ax.set_zlabel("# Observations")

xpos = [1,2,3,4,5,6,7,8,9,10,11,12]#
ypos = [2,4,6,8,10,12,14,16,18,20,22,24]#
zpos = np.zeros(12)

dx = np.ones(12)
dy = np.ones(12)
dz = [100,3,47,35,8,59,24,19,89,60,11,25]
colors=['pink']
ax.bar3d(xpos,ypos,zpos,dx,dy,dz,color=colors)

enter image description here


Solution

  • The color= parameter to bar3d can be a list of colors with one entry per bar. Such a list can be built using a colormap.

    Here is an example that colors the bars using a smooth range from green for the highest and red for the lowest. Changing the colormap to cmap = plt.cm.get_cmap('RdYlGn', 2) would color all the bars higher than the mean in green and the rest in red. To set the split condition exactly at 50, you can change the norm to norm = mcolors.Normalize(0, 100).

    If only a few different colors are needed, the easiest is to forget about cmap and norm and just use:

    colors = ['limegreen' if u > 50 else 'crimson' for u in dz]
    

    Here is a complete example:

    from mpl_toolkits.mplot3d import Axes3D
    import matplotlib.pyplot as plt
    import matplotlib.colors as mcolors
    import numpy as np
    
    fig = plt.figure()
    ax = fig.add_subplot(111, projection="3d")
    
    ax.set_xlabel("Cumulative HH's")
    ax.set_ylabel("Index")
    ax.set_zlabel("# Observations")
    
    xpos = np.arange(1, 13)
    ypos = np.arange(2, 26, 2)
    zpos = np.zeros(12)
    
    dx = np.ones(12)
    dy = np.ones(12)
    dz = [100, 3, 47, 35, 8, 59, 24, 19, 89, 60, 11, 25]
    cmap = plt.cm.get_cmap('RdYlGn')
    norm = mcolors.Normalize(min(dz), max(dz))
    colors = [cmap(norm(u)) for u in dz]
    ax.bar3d(xpos, ypos, zpos, dx, dy, dz, color=colors)
    
    plt.show()
    

    At the left an example with a range of colors, at the right an example with only 2 colors:

    example plot