Issue
I have a two-dimensional numpy array that is a set of values for some parameter. Part of the data in this array is missing and is of type numpy.nan. I would like to plot a "heatmap" type graph using a heatmap, pcolor or matshow or imshow, in this case it doesn't matter to me. The color will indicate the value of the parameter. But I faced with some difficulties making this task a time consuming job. The passing of a part of the data in the array is due to my data field for displaying the heatmap is not a rectangle. It is inscribed in a figure that approximates a circle. I assign NaN values to those points in the data matrix that do not belong to the circle. Those in this matrix, the nan-values have points that are not conventionally a circle. Only some columns and rows are filled with data completely. This approach helps me to solve the problem how it is possible to display a heatmap of some arbitrary shape, and not just a rectangle. The figure shows what I want to get approximately.
In this regard, I have two questions:
- When solving the problem with my approach, what heatmap setting can set the color for nan values, since white is not always what I want. I would like to be able to set it of my choice.
- A more global question. Is there an easier way to plot a heatmap for which I can simply specify the x and y coordinates of the data points, and the parameter value (e.g. z) that will be converted to color. I would like not to create a two-dimensional array with part of the missing data, but simply pass array-like objects x, y and z and get such a heatmap. But I want this graph to look like a solid field of rectangular tiles, as shown in my picture, and not like some kind of scatterplot, with multi-colored marker points. In my case, the code that creates the graph looks like this:
import numpy as np
import pandas as pd
import matplotlib as mpl
import matplotlib.pyplot as plt
import datetime
%matplotlib inline
#retrieving and transforming data...
#creating two-dimensional data array
#create_matrix_data_vect - some custom function
data = create_matrix_data_vect(param_data=data.z_parameter, \
positions_data=positions_data_normal, \
data_shape=data_array_shape)
data.shape
(12, 12) - the size can be much larger
The data array looks like this:
array([[ nan, nan, nan, nan, 201. , 195. , 203. , 196. , nan,
nan, nan, nan],
[ nan, nan, nan, 193. , 172. , 181. , 212. , 91.3, 179. ,
nan, nan, nan],
[ nan, nan, 188. , 208. , 180. , 201. , 239. , 243. , 254. ,
253. , nan, nan],
[ nan, 232. , 234. , 224. , 266. , 263. , 258. , 218. , 215. ,
200. , 192. , nan],
[ nan, 211. , 201. , 194. , 190. , 199. , 196. , 187. , 200. ,
199. , 192. , nan],
[ nan, 200. , 202. , 207. , 201. , 195. , 203. , 196. , 193. ,
172. , 181. , nan],
[ nan, 212. , 91.3, 179. , 188. , 208. , 180. , 201. , 239. ,
243. , 254. , nan],
[ nan, 253. , 232. , 234. , 224. , 266. , 263. , 258. , 218. ,
215. , 200. , nan],
[ nan, 192. , 211. , 201. , 194. , 190. , 199. , 196. , 187. ,
200. , 199. , nan],
[ nan, nan, 192. , 200. , 202. , 207. , 201. , 195. , 203. ,
196. , nan, nan],
[ nan, nan, nan, 193. , 172. , 181. , 212. , 91.3, 179. ,
nan, nan, nan],
[ nan, nan, nan, nan, 188. , nan, nan, 208. , nan,
nan, nan, nan]])
This code is used to draw the graph:
bounds = np.linspace(param_ng, param_vg,continious_color_map.N)\
.reshape(continious_color_map.N,)
norm = mpl.colors.BoundaryNorm(bounds, continious_color_map.N)
fig, ax = plt.subplots(1, 1, figsize = (7, 7))
img = ax.matshow(data, cmap=continious_color_map, norm=norm)
divider = make_axes_locatable(ax)
cax = divider.append_axes("right", size='5%', pad='1%')
fig.colorbar(img, cax=cax, ax=ax, ticks=bounds)
I would be grateful for any help
Solution
You can set the color for nan
values via .set_bad()
to the colormap.
To create an image from ungridded x,y,z positions, you can use contourf()
:
import matplotlib.pyplot as plt
import matplotlib as mpl
import numpy as np
from numpy import nan
data = np.array([[nan, nan, nan, nan, 201., 195., 203., 196., nan, nan, nan, nan],
[nan, nan, nan, 193., 172., 181., 212., 91.3, 179., nan, nan, nan],
[nan, nan, 188., 208., 180., 201., 239., 243., 254., 253., nan, nan],
[nan, 232., 234., 224., 266., 263., 258., 218., 215., 200., 192., nan],
[nan, 211., 201., 194., 190., 199., 196., 187., 200., 199., 192., nan],
[nan, 200., 202., 207., 201., 195., 203., 196., 193., 172., 181., nan],
[nan, 212., 91.3, 179., 188., 208., 180., 201., 239., 243., 254., nan],
[nan, 253., 232., 234., 224., 266., 263., 258., 218., 215., 200., nan],
[nan, 192., 211., 201., 194., 190., 199., 196., 187., 200., 199., nan],
[nan, nan, 192., 200., 202., 207., 201., 195., 203., 196., nan, nan],
[nan, nan, nan, 193., 172., 181., 212., 91.3, 179., nan, nan, nan],
[nan, nan, nan, nan, 188., nan, nan, 208., nan, nan, nan, nan]])
continious_color_map = plt.get_cmap('Spectral', 20)
continious_color_map.set_bad('purple')
bounds = np.linspace(np.nanmin(data), np.nanmax(data), continious_color_map.N)
norm = mpl.colors.BoundaryNorm(bounds, continious_color_map.N)
fig, (ax1, ax2) = plt.subplots(ncols=2, figsize=(14, 6))
img1 = ax1.matshow(data, cmap=continious_color_map, norm=norm)
plt.colorbar(img1, ax=ax1, shrink=0.9)
xs = [i for row in data for i, x in enumerate(row) if not np.isnan(x)]
ys = [j for j, row in enumerate(data) for y in row if not np.isnan(y)]
zs = [d for row in data for d in row if not np.isnan(d)]
img2 = ax2.tricontourf(xs, ys, zs, levels=bounds, cmap=continious_color_map, norm=norm)
ax2.set_aspect('equal')
ax2.set_facecolor('magenta')
ax2.invert_yaxis()
plt.colorbar(img2, ax=ax2, shrink=0.9)
plt.tight_layout()
plt.show()
Answered By - JohanC
0 comments:
Post a Comment
Note: Only a member of this blog may post a comment.