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 necessa
Implementation of @ImportanceOfBeingErnest solution:
Used the stacking of colormaps to create a custom colormap of maps. Basically my function now takes tuples of ([list of columns],multiplier,colormap to apply) and stacks the unique colormaps and groups the percentile data to match the individual colormaps (endpoints were tricky to avoid overlap of coloring). I probably didn't implement it super efficiently, but it works well:
def DFPercentiles_hmapshift(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:
pct=(df.loc[j,i]-min(df.loc[j,:]))/((max(df.loc[j,:])-min(df.loc[j,:]))*1.)
pct=pct-(pct-0.5)*1./40 #have to rescale it to account for endpoints of cmaps
p.loc[j,i]=pct
#print '('+str(max(p.loc[j,:]))+', '+str(min(p.loc[j,:]))+')'
else:
for i in df.index:
for j in df.columns:
pct=(df.loc[i,j]-min(df.loc[:,j]))/((max(df.loc[:,j])-min(df.loc[:,j]))*1.)
pct=pct-(pct-0.5)*1./40 #have to rescale it to account for endpoints of cmaps
p.loc[i,j]=pct
#print '('+str(max(p.loc[:,j]))+', '+str(min(p.loc[:,j]))+')'
return p
def Heatmap(df,figsize='auto',ccmaps=[(['Default'],0,'coolwarm')]):
if figsize=='auto':
figsize=[shape(df)[1],shape(df)[0]/2]
fig=figure(figsize=figsize)
#pdf=array(DFPercentiles(df,bycols=True)).astype(float)[::-1]
pdf=DFPercentiles_hmapshift(df,bycols=True)
if len(ccmaps)==1:
cmap=ccmaps[0][2]
else:
cmapl=[]
for x in ccmaps:
if x[1]!=0:
for y in x[0]:
pdf[y]=pdf[y]+x[1]
cmapl.append(getattr(plt.cm,x[2])(np.linspace(0,1,256,endpoint=False)+0.5/256.))
pdf=np.divide(pdf,len(ccmaps))
cs=np.vstack(cmapl)
cmap=matplotlib.colors.LinearSegmentedColormap.from_list("custom",cs)
pdf=array(pdf).astype(float)[::-1]
plt.pcolormesh(pdf,cmap=cmap,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,ccmaps=[(['Default'],0,'RdBu_r'),(['Field3','Field4'],1,'Greens'),
(['Field0'],2,'Greys')])
hmap.show()
for the beautiful (ok, it's just an example!) result: