Charlietrypsin
Charlietrypsin

Reputation: 107

Creating a matplotlib heatmap with two different coloured data sets

I currently have two large data sets, and I want to compare them. I have them separately, one in red and one in blue, however I would like to show the red and blue side by side. How might I go about this?

My current code is:

column_labels = list(heatmap_ylabels)
row_labels = list(heatmap_xlabels)
fig, ax = plt.subplots()
heatmap = ax.pcolor(data, cmap=plt.cm.Reds)

ax.set_xticks(np.arange(9+0.5))
ax.set_yticks(np.arange(140+0.5))

ax.invert_yaxis()
ax.xaxis.tick_top()
ax.set_xticklabels(row_labels, minor=False)
ax.set_yticklabels(column_labels, minor=False)
#plt.show()
plt.savefig('n1_heatmap')
plt.clf()

column_labels = list(heatmap_ylabels)
row_labels = list(heatmap_xlabels)
fig, ax = plt.subplots()
heatmap = ax.pcolor(data1, cmap=plt.cm.Blues)

ax.set_xticks(np.arange(9+0.5))
ax.set_yticks(np.arange(140+0.5))

ax.invert_yaxis()
ax.xaxis.tick_top()
ax.set_xticklabels(row_labels, minor=False)
ax.set_yticklabels(column_labels, minor=False)
plt.savefig('n2_heatmap')
plt.clf()

Both data and data1 are formed of 140 different lists with information extracted from 280 different files, is there a way I can still use these two lists in order to create a heatmap which will show these data in the same figure?

So for example my heatmap will be /red/blue/red/blue etc

Here is an example of my heatmap:

enter image description here

EDIT:

While not showing exactly what I want, I have made a heatmap of the difference in values between the two previous heatmaps.

eg: y2 = np.subtract(y, y1)

data2.append(y2)
column_labels = list(heatmap_ylabels)
row_labels = list(heatmap_xlabels)
fig, ax = plt.subplots()
heatmap = ax.pcolor(data2, cmap=plt.cm.bwr)

ax.set_xticks(np.arange(9+0.5))
ax.set_yticks(np.arange(140+0.5))

ax.invert_yaxis()
ax.xaxis.tick_top()
ax.set_xticklabels(row_labels, minor=False)
ax.set_yticklabels(column_labels, minor=False)
plt.savefig('diff_heatmap')
plt.clf()

Upvotes: 4

Views: 2729

Answers (1)

Joe Kington
Joe Kington

Reputation: 284702

As @jeanrjc mentioned, this is conceptually very similar to a a previously-asked question. However, it's probably not obvious how to apply that method in your case.

Here's a minimal example of plotting two arrays with the same shape "side-by-side" with two different colormaps. The key is to independently plot two masked arrays. To create these masked arrays, we'll make new arrays with double the number of columns and mask every other column.

Here's a simple example (note that there are several ways to create the masked array pattern):

import numpy as np
import matplotlib.pyplot as plt

# Generate data
nrows, ncols = 20, 5
x = np.random.random((nrows, ncols))
y = np.random.random((nrows, ncols))

# Make data for display
mask = np.array(nrows * [ncols * [False, True]], dtype=bool)
red = np.ma.masked_where(mask, np.repeat(x, 2, axis=1))

mask = np.array(nrows * [ncols * [True, False]], dtype=bool)
blue = np.ma.masked_where(mask, np.repeat(y, 2, axis=1))

# Make a side-by-side plot
fig, ax = plt.subplots()
ax.pcolormesh(red, cmap='Reds')
ax.pcolormesh(blue, cmap='Blues')
plt.show()

enter image description here

And if we wanted to make a fancier version, we could do something similar to:

import numpy as np
import matplotlib.pyplot as plt

# Generate data
nrows, ncols = 20, 5
x = np.exp(np.random.normal(0, 0.8, (nrows, ncols)))
y = np.exp(np.random.normal(0, 1, (nrows, ncols)))

# Make data for display
mask = np.array(nrows * [ncols * [False, True]], dtype=bool)
red = np.ma.masked_where(mask, np.repeat(x, 2, axis=1))

mask = np.array(nrows * [ncols * [True, False]], dtype=bool)
blue = np.ma.masked_where(mask, np.repeat(y, 2, axis=1))

# Make a side-by-side plot
fig, ax = plt.subplots()
redmesh = ax.pcolormesh(red, cmap='Reds')
bluemesh = ax.pcolormesh(blue, cmap='Blues')

# Make things a touch fancier
ax.set(xticks=np.arange(1, 2 * ncols, 2),
       yticks=np.arange(nrows) + 0.5,
       xticklabels=['Column ' + letter for letter in 'ABCDE'],
       yticklabels=['Row {}'.format(i+1) for i in range(nrows)])

ax.set_title('Side-by-Side Plot', y=1.07)
ax.xaxis.tick_top()
ax.yaxis.tick_left()
ax.tick_params(direction='out')

# Add dual colorbars
fig.subplots_adjust(bottom=0.05, right=0.78, top=0.88)
cbar = fig.colorbar(redmesh, cax=fig.add_axes([0.81, 0.05, 0.04, 0.83]))
cbar.ax.text(0.55, 0.1, 'Variable 1', rotation=90, ha='center', va='center',
             transform=cbar.ax.transAxes, color='gray')
cbar = fig.colorbar(bluemesh, cax=fig.add_axes([0.9, 0.05, 0.04, 0.83]))
cbar.ax.text(0.55, 0.1, 'Variable 2', rotation=90, ha='center', va='center',
             transform=cbar.ax.transAxes, color='gray')

# Make the grouping clearer
ax.set_xticks(np.arange(0, 2 * ncols, 2), minor=True)
ax.grid(axis='x', ls='-', color='gray', which='minor')
ax.grid(axis='y', ls=':', color='gray')

plt.show()

enter image description here

Upvotes: 5

Related Questions