0

I have this DataFrame df:

df = pd.DataFrame(columns=["System","F1", "F2", "F3", "F4"], 
                  data=[["System1",0,1,0,0],
                        ["System2",0,1,0,0]])

I want to create a "heatmap" of seaborn:

plt.figure(figsize=(12,6))
ax = sns.heatmap(df, annot=False, linewidths=.5, cmap="Set3")
plt.ylabel('Features', fontsize=12)
plt.xlabel('Systems', fontsize=12)
plt.xticks(rotation='vertical')
plt.yticks(rotation='horizontal')
plt.show()

In the X axis I want to have Systems, while in the Y axis I want to have Features. If the System-Feature value is 0, then the color is dark blue, otherwise it's light blue.

How can I do it?

akilat90
  • 5,436
  • 7
  • 28
  • 42
Dinosaurius
  • 8,306
  • 19
  • 64
  • 113

2 Answers2

4

Something like sns.heatmap

sns.heatmap(df.set_index('System'))

In order control the color

from matplotlib import colors
cmap = colors.ListedColormap(['darkblue','blue'])
sns.heatmap(df.set_index('System'),cmap=cmap)

Control the color

from matplotlib import colors
cmap = colors.ListedColormap(['darkblue','blue'])
bounds=[0, 1,99]
norm = colors.BoundaryNorm(bounds, cmap.N)
sns.heatmap(df.set_index('System'),cmap=cmap,norm =norm )
BENY
  • 317,841
  • 20
  • 164
  • 234
1

Edit:

Inverted colormaps will solve your problem of assigning a darker color to smaller values. Adding a legend as per ypur requirement is also somewhat involved. I don't think they're mentioned in the other (original) question.


plt.imshow()

If the values are binary, I don't think there's actually a need to go for a heatmap. You can just use plt.imshow() and set the tick values as per your requirement. Then you also have to draw the pixel boundaries as well- which is a bit like reinventing the wheel though.

df.set_index('System', inplace=True)

plt.figure()
im = plt.imshow(df.values.T, cmap='Blues_r')

ax = plt.gca();

# Playing around with the ticks
ax.set_xticks(np.arange(0, df.shape[0], 1));
ax.set_yticks(np.arange(0, df.shape[1], 1));


# dataframe columns and index values as tick labels
ax.set_xticklabels(df.index.get_values());
ax.set_yticklabels(df.columns);

# to draw the grid lines
ax.set_xticks(np.arange(-.5, df.shape[0], 1), minor=True);
ax.set_yticks(np.arange(-.5, df.shape[1], 1), minor=True);

ax.grid(which='minor', color='b')

plt.ylabel('Features', fontsize=12)
plt.xlabel('Systems', fontsize=12)

Using this answer and some augmentations to show the patches.

import matplotlib.patches as mpatches

values = np.unique(df.values.ravel())

colors = [ im.cmap(im.norm(value)) for value in values]

patches = [ mpatches.Patch(color=colors[i], label="{l}".format(l=values[i]) , edgecolor='b' ) for i in range(len(values)) ]

legend=plt.legend(handles=patches, bbox_to_anchor=(1.05, 1),loc=2, borderaxespad=0.5, frameon=True)
frame = legend.get_frame() # to add a frame
frame.set_facecolor('grey')


plt.show()

![enter image description here

sns.heatmap()

(Incomplete answer)

sns.heatmap(df.T, annot=False, linewidths=.5, cmap="Blues_r", linecolor='b')# Blues cmap has been inverted by appending '_r'

enter image description here

akilat90
  • 5,436
  • 7
  • 28
  • 42