Search code examples
python-3.xmatplotlibcolorbar

Plot list as a colorbar to efficiently visualize outliers


I'd like to generate a colorbar for values stored in a list

def map_values_to_color(data: List, cmap: str, integer=False):
   
    norm = matplotlib.colors.Normalize(vmin=min(data), vmax=max(data), clip=True)
    mapper = cm.ScalarMappable(norm=norm, cmap=cmap)

    if integer:
        color = [[r, g, b] for r, g, b, a in mapper.to_rgba(data, bytes=True)]
    else:
        color = [[r, g, b] for r, g, b, a in mapper.to_rgba(data)]

    colorlist = [(val, color) for val, color in zip(data, color)]

    return colorlist
    
if __name__ == '__main__':


    vals = [100, .80, .10, .79, .70, .60, .75, .78, .65, .90] 

    colorlist = map_values_to_color(data=vals, cmap='bwr_r', integer=True)

Any suggestions on how to generate just the colorbar will be really helpful.

EDIT: Output obtained from the below code:

enter image description here

EDIT2: The below answer might be useful for lists without outliers. However, my data has outliers and I am still looking for suggestions/ inputs on how to visualize the data with outliers efficiently using a colorbar i.e some sort of a discrete colorbar.


Solution

  • As they told you, you need a 2-d array to use imshow, but you need a 1-row, N-columns array to represent the inherently mono-dimensionality of a list.

    Further, we can apply a little bit of cosmetics to the ticks to simplify the plot (I removed the y ticks because you do not really have an y axis) and to make easier to identify the outliers (I specified a denser set of x ticks — beware that for a really long list this must be adapted in some way).

    Last but not least, you have a strict definition of outliers and want a colormap describing in detail the correct range and evidencing the outliers, with this regard I have adapted an answer by Joe Kington, in which we modify the colormap to show contrasting colors for the outliers and specify, at the level of imshow, which is the range outside of which we have outliers.

    Here it is my script (note the extended slicing syntax that makes a 1-d array a 2-d one, the use of vmin and vmax, the use of `extend='both' and how we set the contrasting colors for the outliers)

    import numpy as np
    import matplotlib.pyplot as plt
    
    vals = [100, .80, .10, .79, .70, -80, .75, .78, .65, .90]
    arr = np.array(vals)[None, :] # arr.shape ⇒ (1, 10)
    ###   #######################
    im = plt.imshow(arr, vmin=0, vmax=1, cmap='bwr')                
    cbar = plt.colorbar(im, extend='both', orientation='horizontal')
    cbar.cmap.set_under('yellow') , cbar.cmap.set_over('green')
    plt.xticks(range(len(vals))), plt.yticks(())
    plt.show
    

    The script produces

    enter image description here