Построение 2D тепловой карты с помощью Matplotlib

139

Используя Matplotlib, я хочу построить 2D тепловую карту. Мои данные представляют собой массив Numpy размером n на n, каждый со значением от 0 до 1. Итак, для элемента (i, j) этого массива я хочу построить квадрат с координатой (i, j) в моем тепловая карта, цвет которой пропорционален значению элемента в массиве.

Как я могу это сделать?

Karnivaurus
источник
2
Вы вообще смотрели matplotlibгалерею перед публикацией? Есть несколько хороших примеров использования imshow, pcolorи они pcolormeshделают то, что вы хотите
tmdavison

Ответы:

189

imshow()Функции с параметрами interpolation='nearest'и cmap='hot'должны делать то , что вы хотите.

import matplotlib.pyplot as plt
import numpy as np

a = np.random.random((16, 16))
plt.imshow(a, cmap='hot', interpolation='nearest')
plt.show()

введите описание изображения здесь

П. Камиллери
источник
1
Я не думаю, что указывать интерполяцию необходимо.
miguel.martin
2
@ miguel.martin согласно документу pyplot: «Если интерполяция None (значение по умолчанию), по умолчанию используется rc image.interpolation». Так что я считаю, что это необходимо включить.
П. Камиллери
@ P.Camilleri Как масштабировать оси X и Y? (Меняем только цифры, без увеличения).
Dole
64

Seaborn берет на себя большую часть ручной работы и автоматически рисует градиент сбоку от диаграммы и т. Д.

import numpy as np
import seaborn as sns
import matplotlib.pylab as plt

uniform_data = np.random.rand(10, 12)
ax = sns.heatmap(uniform_data, linewidth=0.5)
plt.show()

введите описание изображения здесь

Или вы даже можете построить верхний / нижний левый / правый треугольники квадратных матриц, например, квадратную и симметричную корреляционную матрицу, поэтому отображение всех значений в любом случае будет избыточным.

corr = np.corrcoef(np.random.randn(10, 200))
mask = np.zeros_like(corr)
mask[np.triu_indices_from(mask)] = True
with sns.axes_style("white"):
    ax = sns.heatmap(corr, mask=mask, vmax=.3, square=True,  cmap="YlGnBu")
    plt.show()

введите описание изображения здесь

PyRsquared
источник
1
Я очень люблю сюжетный тип, и полуматрица мне пригодится. Два вопроса: 1) на первом графике квадратики разделены белыми линиями, можно ли их соединить? 2) ширина белой линии кажется разной, это артефакт?
П. Камиллери
1
Вы можете использовать аргумент 'ширина линии', который я использовал в первом графике, для любого другого графика (например, во втором графике), чтобы получить разнесенные квадраты. Ширина линий меняется только на первом графике из-за проблем со снимками экрана, на самом деле они не меняются в действительности, они должны оставаться на том уровне, который вы их установили.
PyRsquared
хотя это правда - я не думаю, что ответ с использованием seaborn следует считать полным для вопроса, в котором конкретно указывается matplotlib.
baxx
28

Для двумерного numpyмассива imshow()вам может помочь простое использование :

import matplotlib.pyplot as plt
import numpy as np


def heatmap2d(arr: np.ndarray):
    plt.imshow(arr, cmap='viridis')
    plt.colorbar()
    plt.show()


test_array = np.arange(100 * 100).reshape(100, 100)
heatmap2d(test_array)

Тепловая карта примера кода

Этот код создает непрерывную тепловую карту.

Вы можете выбрать другие встроенные colormapиз здесь .

huangbiubiu
источник
18

Я бы использовал функцию pcolor / pcolormesh из matplotlib, поскольку она допускает неравномерный интервал между данными.

Пример взят из matplotlib :

import matplotlib.pyplot as plt
import numpy as np

# generate 2 2d grids for the x & y bounds
y, x = np.meshgrid(np.linspace(-3, 3, 100), np.linspace(-3, 3, 100))

z = (1 - x / 2. + x ** 5 + y ** 3) * np.exp(-x ** 2 - y ** 2)
# x and y are bounds, so z should be the value *inside* those bounds.
# Therefore, remove the last value from the z array.
z = z[:-1, :-1]
z_min, z_max = -np.abs(z).max(), np.abs(z).max()

fig, ax = plt.subplots()

c = ax.pcolormesh(x, y, z, cmap='RdBu', vmin=z_min, vmax=z_max)
ax.set_title('pcolormesh')
# set the limits of the plot to the limits of the data
ax.axis([x.min(), x.max(), y.min(), y.max()])
fig.colorbar(c, ax=ax)

plt.show()

вывод графика pcolormesh

Эразм Седернаес
источник
12

Вот как это сделать из CSV:

import numpy as np
import matplotlib.pyplot as plt
from scipy.interpolate import griddata

# Load data from CSV
dat = np.genfromtxt('dat.xyz', delimiter=' ',skip_header=0)
X_dat = dat[:,0]
Y_dat = dat[:,1]
Z_dat = dat[:,2]

# Convert from pandas dataframes to numpy arrays
X, Y, Z, = np.array([]), np.array([]), np.array([])
for i in range(len(X_dat)):
        X = np.append(X, X_dat[i])
        Y = np.append(Y, Y_dat[i])
        Z = np.append(Z, Z_dat[i])

# create x-y points to be used in heatmap
xi = np.linspace(X.min(), X.max(), 1000)
yi = np.linspace(Y.min(), Y.max(), 1000)

# Z is a matrix of x-y values
zi = griddata((X, Y), Z, (xi[None,:], yi[:,None]), method='cubic')

# I control the range of my colorbar by removing data 
# outside of my range of interest
zmin = 3
zmax = 12
zi[(zi<zmin) | (zi>zmax)] = None

# Create the contour plot
CS = plt.contourf(xi, yi, zi, 15, cmap=plt.cm.rainbow,
                  vmax=zmax, vmin=zmin)
plt.colorbar()  
plt.show()

где dat.xyzнаходится в форме

x1 y1 z1
x2 y2 z2
...
килоджоулей
источник
1
Небольшое замечание: мне пришлось изменить метод с кубического на ближайший или линейный, потому что кубический приводил к большому количеству NaN, так как я работаю с довольно маленькими значениями между 0 ... 1
Майкефер