Welcome to OStack Knowledge Sharing Community for programmer and developer-Open, Learning and Share
Welcome To Ask or Share your Answers For Others

Categories

0 votes
390 views
in Technique[技术] by (71.8m points)

python - Single pcolormesh with more than one colormap using Matplotlib

I'm creating a GUI where there is live 'point in time' data for several records ("things") and fields. records are comparable based on field, but fields are not necessarily related (at least not on same scale). For my eventual GUI, I want to have the main page be a heatmap (really a bunch of 1-D heatmaps based on columns (fields), then if you click on one it will give a time series history and some other charts.

Anyway, what I'm after here, is trying to get the initial heatmap to show the way I want. As of now I can get the pcolormesh from Matplotlib to essentially show individual 1-D heatmaps based on field by hacking it and heatmapping based on percentile of column, and then adding text of the actual value on top.

But, as I said, fields are not necessarily related, and I would like to be able to have individual colormaps for each field. For example: say Fields 3 and 4 are qualitatively related to one another, but not to Fields 0-3 - so it would be nice to have those mapped to say the 'greens' colormesh rather than 'coolwarm'.

Here is my code so far and resulting pcolormesh/heatmap:

import pandas as pd
import matplotlib.pyplot as plt

def DFPercentiles(df,bycols=True):
    p=pd.DataFrame(index=df.index,columns=df.columns)
    if bycols!=True:
        for j in df.index:
            for i in df.columns:
                p.loc[j,i]=(df.loc[j,i]-min(df.loc[j,:]))/(max(df.loc[j,:])-min(df.loc[j,:]))
    else:
        for i in df.index:
            for j in df.columns:
                p.loc[i,j]=(df.loc[i,j]-min(df.loc[:,j]))/(max(df.loc[:,j])-min(df.loc[:,j]))
    return p

def Heatmap(df,figsize='auto'):
    if figsize=='auto':
        figsize=[shape(df)[1],shape(df)[0]/2]
    fig=figure(figsize=figsize)
    pdf=array(DFPercentiles(df,bycols=True)).astype(float)[::-1]
    plt.pcolormesh(pdf,cmap=cm.coolwarm,alpha=0.8)
    plt.yticks(arange(0.5,len(df)),df.index[::-1])
    plt.xticks(arange(0.5,len(df.columns)),df.columns)
    for y in range(df.shape[0]):
        for x in range(df.shape[1]):
            plt.text(x + 0.5, y + 0.5, '%.3f' % df[::-1].iloc[y, x],
                     horizontalalignment='center',
                     verticalalignment='center',
                     )
    return plt

hmap=Heatmap(mydf)
hmap.show()

And the result:

Multiple 1-D heatmaps on one pcolormesh, but can't get multiple colormaps

I've had no luck trying to get multiple colormaps for separate fields.

See Question&Answers more detail:os

与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
Welcome To Ask or Share your Answers For Others

1 Answer

0 votes
by (71.8m points)

Each colormesh plot has one colormap associated to it. In order to use several colormaps in one diagram, I therefore see the following options:

  1. Individual rectangles: Don't use pcolormesh but draw individual rectangles in the color of your liking.
  2. Create your custom colormap which incorporates different colormaps within different ranges. E.g. values from 0 to 0.4 are mapped to colors from one colormap and values from 0.4 to 1 to colors from another colormap. This may then look like:

    import matplotlib.pyplot as plt
    import matplotlib.colors
    import numpy as np
    
    x,y = np.meshgrid(range(4), range(4))
    z = np.array([[0.2,.3,.95],[.5,.76,0.4],[.3,.1,.6]]).astype(float)
    mask= np.array([[1,0,0],[1,0,0],[1,1,1]]).astype(float)
    Z = z + mask
    
    c2 = plt.cm.Greens(np.linspace(0,1,128))
    c1 = plt.cm.coolwarm(np.linspace(0,1,128))
    cols = np.vstack((c1, c2))
    cmap=matplotlib.colors.LinearSegmentedColormap.from_list("q", cols)
    
    fig, ax=plt.subplots()
    ax.pcolormesh(x,y,Z, vmin=0, vmax=2, cmap=cmap)
    
    plt.show()
    
  3. Mask the arrays and plot several pcolormesh plots. The following example shows how this might then look like:

        import matplotlib.pyplot as plt
        import numpy as np
        import numpy.ma as ma
    
        x,y = np.meshgrid(range(4), range(4))
        z = np.array([[1,1.3,3],[2.2,2.8,1.8],[3,1,3]]).astype(float)
        mask= np.array([[1,0,0],[1,0,0],[1,1,1]]).astype(bool)
        z1 = np.copy(z)
        z1[mask] = np.nan
    
        z2 = np.copy(z)
        z2[~mask] = np.nan
    
        fig, ax=plt.subplots()
        ax.pcolormesh(x,y,ma.masked_invalid(z1), vmin=1, vmax=3, cmap="coolwarm")
        ax.pcolormesh(x,y,ma.masked_invalid(z2), vmin=1, vmax=3, cmap="Greens")
    
        plt.show()
    

enter image description here


与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
Welcome to OStack Knowledge Sharing Community for programmer and developer-Open, Learning and Share
Click Here to Ask a Question

...