Цветовые карты matplotlib: set_bad не влияет на коллекции - PullRequest
0 голосов
/ 25 сентября 2018

Я хочу использовать параметр set_bad цветовых карт matplotlib, чтобы назначить значениям nan определенный цвет.Я создал цветовую карту:

from matplotlib.colors import ListedColormap, BoundaryNorm

cmap = ListedColormap(['green', 'yellow', 'red'])
norm = BoundaryNorm([0, 20, 70, 100], cmap.N)

Затем я установил плохой цвет на черный:

cmap.set_bad(color="k")

Чтобы убедиться, что все работает как положено, я построил массив как тест, и он работает(нижний левый квадрант черный):

import numpy as np
import matplotlib.pyplot as plt
fig, ax = plt.subplots()
im = ax.imshow(np.array([[10, 50], [np.nan, 70]]), cmap=cmap, norm=norm)
fig.colorbar(im, ax=ax)

Однако, если я использую эту же цветовую карту для коллекций, она не будет работать:

from matplotlib.collections import LineCollection
lc = LineCollection(([(0.1, 0.1), (0.1, 0.2)], [(0.2, .2), (0.2, .3)], [(0.3, .3), (0.3, .4)]))

lc.set_cmap(cmap)
lc.set_norm(norm)
lc.set_array(np.array([10, np.nan, 80]))

fig, ax = plt.subplots()
ax.add_collection(lc)
plt.draw()

Средняя линия получает нанЗначение z и должно быть черным, но оно выходит зеленым.Похоже, что в данном случае nan интерпретируется как 0.

Это ошибка или как-то задумано?Кто-нибудь знает, можно ли использовать set_bad с цветными картами по-другому?

PS: я проверял это с matplotlib 2.2 и 3.0, результат тот же

1 Ответ

0 голосов
/ 26 сентября 2018

Как показано в этой проблеме и прокомментировано @EdSmith, nan s не являются действительными входными данными для цветовых карт.

Вместо этого nan s маскируются до нормы иКарта цветов применяется к ScalarMappable.Эту маскировку необходимо выполнить вручную в течение Collection с.

.set_array(np.ma.masked_invalid([10., np.nan, 80.]))

Полный пример:

import numpy as np
import matplotlib.pyplot as plt
from matplotlib.colors import ListedColormap, BoundaryNorm
from matplotlib.collections import LineCollection

cmap = ListedColormap(['green', 'yellow', 'red'])
cmap.set_bad(color="k")
norm = BoundaryNorm([0, 20, 70, 100], cmap.N)

lc = LineCollection(([(0.1, 0.1), (0.1, 0.2)], [(0.2, .2), (0.2, .3)], [(0.3, .3), (0.3, .4)]))

lc.set_cmap(cmap)
lc.set_norm(norm)
lc.set_array(np.ma.masked_invalid([10., np.nan, 80.]))

fig, ax = plt.subplots()
ax.add_collection(lc)
plt.show()

image

...