How to create a heatmap with uneven mesh size from pandas dataset?

Viewed 60

I want to create a plot that looks something like this which maps values to a user defined mesh size to represent a physical geometry.

enter image description here

I was looking for a way to create heatmaps and saw that seaborn has a function that creates heatmaps. The code below makes the heatmap, however, the mesh is equal size and does not represent the geometry that I want.

Here is the input.

import seaborn as sns
import matplotlib.pyplot as plt
import numpy as np
import pandas as pd

# Numpy arrays
IFE_x = np.array([7.11815 ,7.19875 ,7.34769 ,7.496   ,7.7413  ,
7.98354 , 8.22184 , 8.45534 , 8.77249 , 9.076   , 9.32338 ,
9.59487 , 9.84534 , 10.04127, 10.24567, 10.4217 , 10.54814,
10.63518, 10.70466, 10.74704, 10.77731])
IFE_x = np.repeat(IFE_x, 19)
IFE_y = np.array([24.90 ,24.40 , 23.40 , 22.40 , 21.00 ,16.00 , 11.00 ,6.00, 1.00,
-1.00 ,-6.00 ,-11.00,-16.00,-21.00,-22.40,-23.40,-24.40,-24.90,-25.40])
IFE_y = np.tile(IFE_y, 21)
IFE_ratio = np.array([1.0155, 0.9938, 0.9872, 0.9959, 1.0112, 0.9983,
1.0054, 0.9910, 1.0042, 0.9994, 1.0028, 1.0016, 1.0127, 1.0094, 1.0115,
0.9852, 0.9989, 0.9896, 0.9968, 1.0156, 0.9999, 0.9950, 1.0074, 0.9979,
0.9967, 1.0036, 0.9962, 1.0046, 0.9960, 1.0015, 1.0040, 1.0120, 1.0099,
1.0138, 1.0059, 1.0341, 0.9593, 1.0268, 0.9871, 0.9954, 0.9994, 1.0217,
0.9832, 1.0012, 1.0040, 1.0038, 0.9995, 0.9957, 0.9950, 1.0011, 1.0014,
0.9973, 0.9999, 1.0006, 1.0120, 1.0041, 1.0096, 1.0077, 0.9821, 0.9897,
0.9970, 0.9848, 1.0046, 0.9986, 0.9953, 0.9928, 0.9911, 1.0070, 0.9934,
1.0063, 1.0025, 0.9867, 1.0136, 1.0220, 1.0072, 1.0053, 1.0058, 0.9928,
0.9989, 0.9953, 0.9976, 1.0005, 1.0070, 0.9952, 0.9960, 0.9988, 0.9965,
1.0036, 1.0013, 0.9991, 0.9928, 0.9848, 1.0156, 0.9888, 0.9735, 0.9852,
1.0064, 1.0075, 0.9936, 1.0157, 0.9964, 1.0015, 1.0004, 0.9999, 1.0036,
1.0012, 0.9945, 1.0037, 0.9979, 0.9838, 0.9880, 1.0116, 1.0200, 1.0194,
0.9992, 0.9999, 0.9888, 0.9898, 0.9872, 0.9953, 1.0007, 1.0044, 0.9978,
0.9867,1.0073,1.0041,1.0048,1.0048, 0.9954,1.0056,
1.0090,1.0100,0.9965,1.0060,1.0008,1.0112,0.9984,1.0087,0.9985,1.0014,1.0083,
1.0037,0.9986,1.0043,1.0043,0.9990,1.0033,1.0049,0.9849,1.0026,1.0261,1.0203,0.9953,
0.9884,1.0120,0.9945,1.0032,1.0016,1.0031,1.0019,1.0016,0.9993,1.0037,0.9997,0.9977,1.0009,
1.0064,1.0026,1.0066,1.0020,1.0198,0.9736,0.9966,0.9930,1.0088,1.0036,1.0078,1.0072,
1.0012,1.0027,0.9968,0.9971,0.9969,0.9992,1.0021,0.9847,1.0125,0.9966,0.9927,
1.0105,0.9805,0.9927,0.9782,0.9937,1.0158,1.0032,0.9990,0.9968,1.0003,0.9919,1.0039,
1.0014,0.9996,0.9989,0.9990,0.9928,0.9855,1.0040,0.9954,0.9958,0.9974,1.0093,0.9886,
0.9969,0.9940,0.9989,0.9982,0.9997,0.9922,0.9941,0.9970,1.0017,0.9943,0.9930,0.9952,0.9945,
0.9659,0.9881,0.9847,1.0074,0.9939,0.9969,1.0119,0.9979,0.9974,1.0034,0.9989,1.0021,
0.9893,0.9976,1.0081,1.0012,0.9904,1.0096,1.0052,1.0037,0.9991,1.0073,1.0055,1.0130,
1.0042,1.0055,0.9923,0.9965,0.9953,1.0010,1.0086,0.9900,1.0050,1.0073,1.0017,0.9926,
0.9980,0.9993,0.9965,0.9987,0.9896,0.9833,1.0036,1.0025,0.9982,0.9962,0.9941,0.9904,
1.0061,1.0026,0.9871,1.0031,1.0042,0.9986,0.9848,1.0061,1.0061,0.9882,1.0033,1.0014,
0.9935,0.9885,0.9986,0.9979,1.0016,0.9999,0.9946,1.0033,0.9965,0.9934,0.9986,1.0020,
1.0026,0.9950,1.0035,1.0017,1.0030,0.9906,0.9970,1.0020,0.9969,0.9869,1.0037,0.9979,1.0019,
1.0000,0.9984,0.9985,0.9918,1.0029,1.0025,0.9989,1.0071,1.0110,1.0122,1.0183,0.9722,1.0052,
1.0038,1.0121,0.9916,0.9883,0.9993,1.0011,0.9963,1.0038,0.9918,0.9895,1.0007,0.9969,
0.9994,1.0028,0.9950,1.0053,1.0092,0.9779,0.9940,0.9921,0.9991,1.0036,0.9855,0.9951,1.0091,0.9943,
0.9988,0.9931,0.9891,0.9978,0.9965,0.9936,1.0048,0.9997,0.9882,0.9933,1.0087,0.9844,
1.0047,0.9975,0.9951,0.9946,0.9949,1.0035,0.9900,0.9967,0.9912,0.9883,0.9959,0.9898,
1.0009,0.9983,0.9957,1.0030,0.9900,1.0037,1.0078,0.9970,1.0008,0.9866,1.0003,0.9973,1.0057,
0.9929,0.9918,0.9871,0.9988,1.0040,0.9905,1.0012,0.9739,0.9985,1.0050,0.9901,1.0206])

# Pandas dataframe and plot creation
df = pd.DataFrame({'X': IFE_x, 'Y': IFE_y, 'Ratio': IFE_ratio})
table = df.pivot('Y', 'X', 'Ratio')
ax = sns.heatmap(table)
ax.invert_yaxis()
plt.show()

The output I get is the following image. However, I do not want equally spaced mesh. Is there a way to change the way the mesh is spaced on the plot to create something more similar to the first image in this post? Thank you for your help.

enter image description here

1 Answers

As suggested by JohanC in the comment to your question, you can use matplotlib.axes.Axes.pcolormesh. In order to do this, as explained in the documentation, you need:

  • an array-like X for x axis
  • an array-like Y for y axis
  • a matrix-like C of mapped values

You can use IFE_x and IFE_y for the first two, respectively, without any manipulation. Insted you need to reshape IFE_ratio as a matrix, with:

IFE_ratio = np.reshape(IFE_ratio, (len(IFE_x), len(IFE_y)))

now you can draw the plot:

fig, ax = plt.subplots()

ax.pcolormesh(IFE_x, IFE_y, IFE_ratio.T)

plt.show()

Note that you need to transpose IFE_ratio with .T method, in order to properly draw this plot.

Complete Code

import matplotlib.pyplot as plt
import numpy as np


IFE_x = np.array([7.11815 ,7.19875 ,7.34769 ,7.496   ,7.7413  ,
7.98354 , 8.22184 , 8.45534 , 8.77249 , 9.076   , 9.32338 ,
9.59487 , 9.84534 , 10.04127, 10.24567, 10.4217 , 10.54814,
10.63518, 10.70466, 10.74704, 10.77731])

IFE_y = np.array([24.90 ,24.40 , 23.40 , 22.40 , 21.00 ,16.00 , 11.00 ,6.00, 1.00,
-1.00 ,-6.00 ,-11.00,-16.00,-21.00,-22.40,-23.40,-24.40,-24.90,-25.40])

IFE_ratio = np.array([1.0155, 0.9938, 0.9872, 0.9959, 1.0112, 0.9983,
1.0054, 0.9910, 1.0042, 0.9994, 1.0028, 1.0016, 1.0127, 1.0094, 1.0115,
0.9852, 0.9989, 0.9896, 0.9968, 1.0156, 0.9999, 0.9950, 1.0074, 0.9979,
0.9967, 1.0036, 0.9962, 1.0046, 0.9960, 1.0015, 1.0040, 1.0120, 1.0099,
1.0138, 1.0059, 1.0341, 0.9593, 1.0268, 0.9871, 0.9954, 0.9994, 1.0217,
0.9832, 1.0012, 1.0040, 1.0038, 0.9995, 0.9957, 0.9950, 1.0011, 1.0014,
0.9973, 0.9999, 1.0006, 1.0120, 1.0041, 1.0096, 1.0077, 0.9821, 0.9897,
0.9970, 0.9848, 1.0046, 0.9986, 0.9953, 0.9928, 0.9911, 1.0070, 0.9934,
1.0063, 1.0025, 0.9867, 1.0136, 1.0220, 1.0072, 1.0053, 1.0058, 0.9928,
0.9989, 0.9953, 0.9976, 1.0005, 1.0070, 0.9952, 0.9960, 0.9988, 0.9965,
1.0036, 1.0013, 0.9991, 0.9928, 0.9848, 1.0156, 0.9888, 0.9735, 0.9852,
1.0064, 1.0075, 0.9936, 1.0157, 0.9964, 1.0015, 1.0004, 0.9999, 1.0036,
1.0012, 0.9945, 1.0037, 0.9979, 0.9838, 0.9880, 1.0116, 1.0200, 1.0194,
0.9992, 0.9999, 0.9888, 0.9898, 0.9872, 0.9953, 1.0007, 1.0044, 0.9978,
0.9867,1.0073,1.0041,1.0048,1.0048, 0.9954,1.0056,
1.0090,1.0100,0.9965,1.0060,1.0008,1.0112,0.9984,1.0087,0.9985,1.0014,1.0083,
1.0037,0.9986,1.0043,1.0043,0.9990,1.0033,1.0049,0.9849,1.0026,1.0261,1.0203,0.9953,
0.9884,1.0120,0.9945,1.0032,1.0016,1.0031,1.0019,1.0016,0.9993,1.0037,0.9997,0.9977,1.0009,
1.0064,1.0026,1.0066,1.0020,1.0198,0.9736,0.9966,0.9930,1.0088,1.0036,1.0078,1.0072,
1.0012,1.0027,0.9968,0.9971,0.9969,0.9992,1.0021,0.9847,1.0125,0.9966,0.9927,
1.0105,0.9805,0.9927,0.9782,0.9937,1.0158,1.0032,0.9990,0.9968,1.0003,0.9919,1.0039,
1.0014,0.9996,0.9989,0.9990,0.9928,0.9855,1.0040,0.9954,0.9958,0.9974,1.0093,0.9886,
0.9969,0.9940,0.9989,0.9982,0.9997,0.9922,0.9941,0.9970,1.0017,0.9943,0.9930,0.9952,0.9945,
0.9659,0.9881,0.9847,1.0074,0.9939,0.9969,1.0119,0.9979,0.9974,1.0034,0.9989,1.0021,
0.9893,0.9976,1.0081,1.0012,0.9904,1.0096,1.0052,1.0037,0.9991,1.0073,1.0055,1.0130,
1.0042,1.0055,0.9923,0.9965,0.9953,1.0010,1.0086,0.9900,1.0050,1.0073,1.0017,0.9926,
0.9980,0.9993,0.9965,0.9987,0.9896,0.9833,1.0036,1.0025,0.9982,0.9962,0.9941,0.9904,
1.0061,1.0026,0.9871,1.0031,1.0042,0.9986,0.9848,1.0061,1.0061,0.9882,1.0033,1.0014,
0.9935,0.9885,0.9986,0.9979,1.0016,0.9999,0.9946,1.0033,0.9965,0.9934,0.9986,1.0020,
1.0026,0.9950,1.0035,1.0017,1.0030,0.9906,0.9970,1.0020,0.9969,0.9869,1.0037,0.9979,1.0019,
1.0000,0.9984,0.9985,0.9918,1.0029,1.0025,0.9989,1.0071,1.0110,1.0122,1.0183,0.9722,1.0052,
1.0038,1.0121,0.9916,0.9883,0.9993,1.0011,0.9963,1.0038,0.9918,0.9895,1.0007,0.9969,
0.9994,1.0028,0.9950,1.0053,1.0092,0.9779,0.9940,0.9921,0.9991,1.0036,0.9855,0.9951,1.0091,0.9943,
0.9988,0.9931,0.9891,0.9978,0.9965,0.9936,1.0048,0.9997,0.9882,0.9933,1.0087,0.9844,
1.0047,0.9975,0.9951,0.9946,0.9949,1.0035,0.9900,0.9967,0.9912,0.9883,0.9959,0.9898,
1.0009,0.9983,0.9957,1.0030,0.9900,1.0037,1.0078,0.9970,1.0008,0.9866,1.0003,0.9973,1.0057,
0.9929,0.9918,0.9871,0.9988,1.0040,0.9905,1.0012,0.9739,0.9985,1.0050,0.9901,1.0206])

IFE_ratio = np.reshape(IFE_ratio, (len(IFE_x), len(IFE_y)))


fig, ax = plt.subplots()

ax.pcolormesh(IFE_x, IFE_y, IFE_ratio.T)

plt.show()

Plot

enter image description here

Related