Простое решение - добавить график рассеяния с X-образным маркером, чтобы вычеркнуть ненужные ячейки.
import numpy as np; np.random.seed(42)
import matplotlib.pyplot as plt
data = np.random.rand(10,10)
mask = np.zeros_like(data)
mask[np.triu_indices_from(mask)] = True
data_masked = np.ma.array(data, mask=mask)
fig, ax = plt.subplots()
im = ax.imshow(data_masked, cmap="YlGnBu", origin="upper")
fig.colorbar(im)
ax.scatter(*np.argwhere(data_masked.T < 0.4).T, marker="x", color="black", s=100)
plt.show()
Недостатком этого является то, что размер маркера (s
) не зависит от количества ячеек и должен быть скорректирован для разных размеров фигуры.
Следовательно, альтернативой является рисование некоторых линий (X - две пересекающиеся линии) в соответствующих позициях. Здесь мы создаем функцию crossout(points, ax=None, scale=1, **kwargs)
, где scale
- это процент, который должны брать строки из каждой ячейки.
import numpy as np; np.random.seed(42)
import matplotlib.pyplot as plt
from matplotlib.collections import LineCollection
def crossout(points, ax=None, scale=1, **kwargs):
ax = ax or plt.gca()
l = np.array([[[1,1],[-1,-1]]])*scale/2.
r = np.array([[[-1,1],[1,-1]]])*scale/2.
p = np.atleast_3d(points).transpose(0,2,1)
c = LineCollection(np.concatenate((l+p,r+p), axis=0), **kwargs)
ax.add_collection(c)
return c
data = np.random.rand(10,10)
mask = np.zeros_like(data)
mask[np.triu_indices_from(mask)] = True
data_masked = np.ma.array(data, mask=mask)
fig, ax = plt.subplots()
im = ax.imshow(data_masked, cmap="YlGnBu", origin="upper")
fig.colorbar(im)
crossout(np.argwhere(data_masked.T < 0.4), ax=ax, scale=0.8, color="black")
plt.show()
Для scale=0.8
это выглядит как
Обратите внимание , что для pcolormesh
графика или тепловой карты морского дна (которая использует pcolormesh
внутри), необходимо добавить 0.5
к данным, т.е.
np.argwhere(data_masked.T < 0.4)+0.5