Створіть теплову карту в MatPlotLib за допомогою набору даних розкидання


187

У мене є набір точок даних X, Y (близько 10 к), які легко побудувати як графік розкидання, але який я хотів би представити як теплову карту.

Я переглянув приклади в MatPlotLib, і всі вони, здається, вже починаються зі значень комірок теплової карти для створення зображення.

Чи існує метод, який перетворює купу x, y, все різних, в теплову карту (де зони з більшою частотою x, y були б "теплішими")?


Відповіді:


182

Якщо ви не хочете шестикутників, ви можете використовувати функцію numpy histogram2d:

import numpy as np
import numpy.random
import matplotlib.pyplot as plt

# Generate some test data
x = np.random.randn(8873)
y = np.random.randn(8873)

heatmap, xedges, yedges = np.histogram2d(x, y, bins=50)
extent = [xedges[0], xedges[-1], yedges[0], yedges[-1]]

plt.clf()
plt.imshow(heatmap.T, extent=extent, origin='lower')
plt.show()

Це робить теплову карту розміром 50x50. Якщо ви хочете, скажімо, 512x384, можете bins=(512, 384)зателефонувати на дзвінок histogram2d.

Приклад: Приклад теплової карти Matplotlib


1
Я не маю на увазі бути ідіотом, але як ви насправді маєте цей вихід у файл PNG / PDF, а не відображатися лише в інтерактивному сеансі IPython? Я намагаюся зрозуміти це як якийсь звичайний axesекземпляр, де я можу додати заголовок, мітки осі тощо, а потім зробити нормальне, savefig()як я б робив для будь-якого іншого типового сюжету для matplotlib.
gotgenes

3
@gotgenes: не plt.savefig('filename.png')працює? Якщо ви хочете отримати екземпляр осей, використовуйте об'єктно-орієнтований інтерфейс Matplotlib:fig = plt.figure() ax = fig.gca() ax.imshow(...) fig.savefig(...)
ptomato

1
Справді, дякую! Я думаю, я не повністю розумію, що imshow()це за тією ж категорією функцій, що і scatter(). Я, чесно кажучи, не розумію, чому imshow()перетворює 2d масив плаває в блоки відповідного кольору, тоді як я розумію, що scatter()потрібно робити з таким масивом.
gotgenes

14
Попередження про використання imshow для побудови 2d гістограми значень x / y на кшталт цього: за замовчуванням imshow накреслює походження у верхньому лівому куті та переміщує зображення. Що б я зробив, щоб отримати таку ж орієнтацію, як і сюжет розсіювання,plt.imshow(heatmap.T, extent=extent, origin = 'lower')
Джеймі

7
Для тих , хто хоче зробити логарифмічна Colorbar побачити це питання stackoverflow.com/questions/17201172 / ... і просто зробитиfrom matplotlib.colors import LogNorm plt.imshow(heatmap, norm=LogNorm()) plt.colorbar()
tommy.carstensen

109

У лексиконі Matplotlib , я думаю, ви хочете сюжет із гексабіном .

Якщо ви не знайомі з таким типом сюжету, це просто двовимірна гістограма, в якій площина xy тесселюється звичайною сіткою шестикутників.

Отже, з гістограми можна просто підрахувати кількість точок, що падають у кожному шестикутнику, дискретизувати область графіку як набір вікон , призначити кожну точку одному з цих вікон; нарешті, зіставте вікна на кольоровий масив , і ви отримаєте шестигранну діаграму.

Хоча рідше використовуються, ніж наприклад, кола або квадрати, що шестикутники є кращим вибором для геометрії контейнера для шиття.

  • шестикутники мають симетрію найближчого сусіда (наприклад, квадратні бункери не роблять, наприклад, відстань від точки на межі квадрата до точки всередині цього квадрата не скрізь однакова) і

  • шестикутник - це найвищий n-багатокутник, що забезпечує регулярну площину тесселяції (тобто, ви можете сміливо перепрофілювати кухонну підлогу з плиток у формі шестикутної форми, оскільки у вас не буде порожнього простору між плитками, коли ви закінчите - не вірно для всі інші вищі-n, n> = 7, багатокутники).

( Matplotlib використовує термін hexbin plot; так це роблять (AFAIK) всі бібліотеки побудови графіків для R ; досі я не знаю, чи це загальноприйнятий термін для сюжетів такого типу, хоча я підозрюю, що, мабуть, враховується, що hexbin короткий для гексагонального бінінгу , який описує важливий етап підготовки даних до відображення.)


from matplotlib import pyplot as PLT
from matplotlib import cm as CM
from matplotlib import mlab as ML
import numpy as NP

n = 1e5
x = y = NP.linspace(-5, 5, 100)
X, Y = NP.meshgrid(x, y)
Z1 = ML.bivariate_normal(X, Y, 2, 2, 0, 0)
Z2 = ML.bivariate_normal(X, Y, 4, 1, 1, 1)
ZD = Z2 - Z1
x = X.ravel()
y = Y.ravel()
z = ZD.ravel()
gridsize=30
PLT.subplot(111)

# if 'bins=None', then color of each hexagon corresponds directly to its count
# 'C' is optional--it maps values to x-y coordinates; if 'C' is None (default) then 
# the result is a pure 2D histogram 

PLT.hexbin(x, y, C=z, gridsize=gridsize, cmap=CM.jet, bins=None)
PLT.axis([x.min(), x.max(), y.min(), y.max()])

cb = PLT.colorbar()
cb.set_label('mean value')
PLT.show()   

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


Що означає, що "шестикутники мають симетрію найближчого сусіда"? Ви кажете, що "відстань від точки на межі квадрата та точки всередині квадрата не скрізь однакова", але відстань до чого?
Яан

9
Для шестикутника відстань від центру до вершини, що з'єднує дві сторони, також довше, ніж від центру до середини сторони, лише відношення менше (2 / sqrt (3) ≈ 1,15 для шестикутника проти sqrt (2) ≈ 1,41 для квадрата). Єдина форма, де відстань від центру до кожної точки на кордоні дорівнює колу.
Яан

5
@Jaan Для шестикутника кожен сусід знаходиться на однаковій відстані. Немає проблем з 8-квартальним або 4-мікрорайонним. Немає діагональних сусідів, лише один вид сусідки.
ісаранді

@doug Як вибрати gridsize=параметр. Я хотів би вибрати його таким, щоб шестикутники просто торкалися, не перекриваючись. Я помітив, що gridsize=100випускатимуть менші шестикутники, але як вибрати правильне значення?
Олександр Цска

40

Редагувати: Для кращого наближення відповіді Алехандро див. Нижче.

Я знаю, що це давнє питання, але хотів щось додати до прихильника Алехандро: Якщо ви хочете приємно згладити зображення без використання py-sphviewer, ви можете замість цього застосувати np.histogram2dта застосувати scipy.ndimage.filtersдо теплової карти гауссовий фільтр (від ):

import numpy as np
import matplotlib.pyplot as plt
import matplotlib.cm as cm
from scipy.ndimage.filters import gaussian_filter


def myplot(x, y, s, bins=1000):
    heatmap, xedges, yedges = np.histogram2d(x, y, bins=bins)
    heatmap = gaussian_filter(heatmap, sigma=s)

    extent = [xedges[0], xedges[-1], yedges[0], yedges[-1]]
    return heatmap.T, extent


fig, axs = plt.subplots(2, 2)

# Generate some test data
x = np.random.randn(1000)
y = np.random.randn(1000)

sigmas = [0, 16, 32, 64]

for ax, s in zip(axs.flatten(), sigmas):
    if s == 0:
        ax.plot(x, y, 'k.', markersize=5)
        ax.set_title("Scatter plot")
    else:
        img, extent = myplot(x, y, s)
        ax.imshow(img, extent=extent, origin='lower', cmap=cm.jet)
        ax.set_title("Smoothing with  $\sigma$ = %d" % s)

plt.show()

Виробляє:

Вивести зображення

Ділянка розкидання і s = 16 побудована на верхній частині одного для Агапе Галло (натисніть для кращого перегляду):

Зверху на інше


Одна з різниць, які я помітив при моєму підході до фільтра Гаусса та підході Алехандро, полягає в тому, що його метод показує місцеві структури набагато краще, ніж мої. Тому я реалізував простий метод найближчого сусіда на рівні пікселів. Цей метод обчислює для кожного пікселя зворотну суму відстаней nнайближчих точок у даних. Цей метод має високу роздільну здатність, досить обчислювально дорогий, і я вважаю, що існує швидший шлях, тому повідомте мені, чи є якісь вдосконалення.

Оновлення: Як я підозрював, існує набагато швидший метод використання Scipy scipy.cKDTree. Дивіться відповідь Габріеля щодо реалізації.

У всякому разі, ось мій код:

import numpy as np
import matplotlib.pyplot as plt
import matplotlib.cm as cm


def data_coord2view_coord(p, vlen, pmin, pmax):
    dp = pmax - pmin
    dv = (p - pmin) / dp * vlen
    return dv


def nearest_neighbours(xs, ys, reso, n_neighbours):
    im = np.zeros([reso, reso])
    extent = [np.min(xs), np.max(xs), np.min(ys), np.max(ys)]

    xv = data_coord2view_coord(xs, reso, extent[0], extent[1])
    yv = data_coord2view_coord(ys, reso, extent[2], extent[3])
    for x in range(reso):
        for y in range(reso):
            xp = (xv - x)
            yp = (yv - y)

            d = np.sqrt(xp**2 + yp**2)

            im[y][x] = 1 / np.sum(d[np.argpartition(d.ravel(), n_neighbours)[:n_neighbours]])

    return im, extent


n = 1000
xs = np.random.randn(n)
ys = np.random.randn(n)
resolution = 250

fig, axes = plt.subplots(2, 2)

for ax, neighbours in zip(axes.flatten(), [0, 16, 32, 64]):
    if neighbours == 0:
        ax.plot(xs, ys, 'k.', markersize=2)
        ax.set_aspect('equal')
        ax.set_title("Scatter Plot")
    else:
        im, extent = nearest_neighbours(xs, ys, resolution, neighbours)
        ax.imshow(im, origin='lower', extent=extent, cmap=cm.jet)
        ax.set_title("Smoothing over %d neighbours" % neighbours)
        ax.set_xlim(extent[0], extent[1])
        ax.set_ylim(extent[2], extent[3])
plt.show()

Результат:

Найближчий згладжуючий сусід


1
Люблю це. Графік такий же приємний, як і відповідь Алехандро, але нових пакетів не потрібно.
Натан Климент

Дуже хороша ! Але ви генеруєте компенсацію за допомогою цього методу. Це можна побачити, порівнявши звичайний графік розкидання з кольоровим. Чи можете ви додати щось, щоб це виправити? Або просто перемістити графік на значення x і y?
Agape Gal'lo

1
Агапе Галло, що ти маєш на увазі під зсувом? Якщо ви розміщуєте їх поверх інших, вони відповідають (див. Редагування моєї публікації). Можливо, ви відклали, оскільки ширина розкиду не відповідає точно іншим трьом.
Jurgy

Велике спасибі за побудову графіку тільки для мене! Я зрозумів свою помилку: я змінив "ступінь", щоб визначити межі x і y. Тепер я розумію, що це змінило походження графіка. Потім у мене є останнє запитання: як я можу розширити межі графіка навіть для області, де немає даних? Наприклад, від -5 до +5 для x і y.
Агапе Галло

1
Скажіть, що ви хочете, щоб вісь x переходила від -5 до 5, а вісь y від -3 до 4; в myplotфункції, додайте rangeпараметр в np.histogram2d: np.histogram2d(x, y, bins=bins, range=[[-5, 5], [-3, 4]])і в контурі для установки х і у Лім осі: ax.set_xlim([-5, 5]) ax.set_ylim([-3, 4]). Крім того, за замовчуванням imshowзберігає співвідношення сторін ідентичне співвідношенню ваших осей (так, у моєму прикладі співвідношення 10: 7), але якщо ви хочете, щоб воно відповідало вашому вікні сюжету, додайте параметр aspect='auto'до imshow.
Jurgy

31

Замість використання np.hist2d, який загалом видає досить потворні гістограми, я хотів би переробити py-sphviewer , пакет python для надання імітації частинок за допомогою адаптивного ядра згладжування, який легко встановити з pip (див. Документацію на веб-сторінку). Розглянемо наступний код, який базується на прикладі:

import numpy as np
import numpy.random
import matplotlib.pyplot as plt
import sphviewer as sph

def myplot(x, y, nb=32, xsize=500, ysize=500):   
    xmin = np.min(x)
    xmax = np.max(x)
    ymin = np.min(y)
    ymax = np.max(y)

    x0 = (xmin+xmax)/2.
    y0 = (ymin+ymax)/2.

    pos = np.zeros([3, len(x)])
    pos[0,:] = x
    pos[1,:] = y
    w = np.ones(len(x))

    P = sph.Particles(pos, w, nb=nb)
    S = sph.Scene(P)
    S.update_camera(r='infinity', x=x0, y=y0, z=0, 
                    xsize=xsize, ysize=ysize)
    R = sph.Render(S)
    R.set_logscale()
    img = R.get_image()
    extent = R.get_extent()
    for i, j in zip(xrange(4), [x0,x0,y0,y0]):
        extent[i] += j
    print extent
    return img, extent

fig = plt.figure(1, figsize=(10,10))
ax1 = fig.add_subplot(221)
ax2 = fig.add_subplot(222)
ax3 = fig.add_subplot(223)
ax4 = fig.add_subplot(224)


# Generate some test data
x = np.random.randn(1000)
y = np.random.randn(1000)

#Plotting a regular scatter plot
ax1.plot(x,y,'k.', markersize=5)
ax1.set_xlim(-3,3)
ax1.set_ylim(-3,3)

heatmap_16, extent_16 = myplot(x,y, nb=16)
heatmap_32, extent_32 = myplot(x,y, nb=32)
heatmap_64, extent_64 = myplot(x,y, nb=64)

ax2.imshow(heatmap_16, extent=extent_16, origin='lower', aspect='auto')
ax2.set_title("Smoothing over 16 neighbors")

ax3.imshow(heatmap_32, extent=extent_32, origin='lower', aspect='auto')
ax3.set_title("Smoothing over 32 neighbors")

#Make the heatmap using a smoothing over 64 neighbors
ax4.imshow(heatmap_64, extent=extent_64, origin='lower', aspect='auto')
ax4.set_title("Smoothing over 64 neighbors")

plt.show()

який створює таке зображення:

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

Як бачите, зображення виглядають досить приємно, і ми можемо виявити на ньому різні підструктури. Ці зображення побудовані з поширенням заданої ваги для кожної точки в межах певної області, визначеної довжиною згладжування, яка по черзі задається відстанню до ближнього сусіда nb (я вибрав 16, 32 і 64 для прикладів). Отже, регіони з більшою щільністю зазвичай поширюються на менші регіони порівняно з регіонами нижчої щільності.

Функція myplot - це просто дуже проста функція, яку я написав для того, щоб надати x, y дані py-sphviewer, щоб зробити магію.


2
Коментар для тих, хто намагається встановити py-sphviewer на OSX: У мене було досить багато труднощів, дивіться: github.com/alejandrobll/py-sphviewer/issues/3
Сем

Шкода, що він не працює з python3. Він встановлюється, але потім виходить з ладу, коли ви намагаєтесь його використовувати ...
Fábio Dias

1
@Fabio Dias, остання версія (1.1.x) тепер працює з Python 3.
Алехандро

29

Якщо ви використовуєте 1.2.x

import numpy as np
import matplotlib.pyplot as plt

x = np.random.randn(100000)
y = np.random.randn(100000)
plt.hist2d(x,y,bins=100)
plt.show()

gaussian_2d_heat_map


17

Seaborn тепер має функцію спільного виробництва, яка тут повинна добре працювати:

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

# Generate some test data
x = np.random.randn(8873)
y = np.random.randn(8873)

sns.jointplot(x=x, y=y, kind='hex')
plt.show()

демо-зображення


Простий, симпатичний і аналітично корисний.
ryanjdillon

@wordsforthewise Як зробити 600K візуально читабельних даних за допомогою цього? (як змінити розмір)
nrmb

Я не зовсім впевнений, що ти маєш на увазі; можливо, найкраще вам задати окреме запитання і зв’язати його тут. Ви маєте на увазі розмір усієї фігури? Спочатку зробіть фігуру за допомогою fig = plt.figure(figsize=(12, 12)), потім отримайте поточну вісь ax=plt.gca(), потім додайте аргумент ax=axдо jointplotфункції.
словазвідти

@wordsforthewise могли б ви відповісти на це питання: stackoverflow.com/questions/50997662 / ... спасибі
Ebrahimi

4

і початкове питання було ... як перетворити значення розкидання в значення сітки, правда? histogram2dобчислює частоту на комірку, однак, якщо у вас є інші дані на комірку, ніж просто частота, вам знадобиться додаткова робота.

x = data_x # between -10 and 4, log-gamma of an svc
y = data_y # between -4 and 11, log-C of an svc
z = data_z #between 0 and 0.78, f1-values from a difficult dataset

Отже, у мене є набір даних із Z-результатами для координат X та Y. Однак я підраховував декілька балів за межами області, що цікавить (великі прогалини), і купи балів на невеликій цікавій області.

Так, тут стає важче, але й веселіше. Деякі бібліотеки (вибачте):

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

pyplot - це мій графічний двигун сьогодні, cm - це діапазон кольорових карт з певним цікавим вибором. numpy для обчислень та griddata для приєднання значень до нерухомої сітки.

Останнє важливе, особливо тому, що частота точок xy в моїх даних не однаково розподілена. Спочатку почнемо з деяких меж, що відповідають моїм даним та довільного розміру сітки. У вихідних даних є точки даних також поза межами x та y.

#determine grid boundaries
gridsize = 500
x_min = -8
x_max = 2.5
y_min = -2
y_max = 7

Отже, ми визначили сітку з 500 пікселями між значеннями min та max x та y.

За моїми даними, є набагато більше, ніж 500 значень, доступних у зоні, що викликає великий інтерес; оскільки в зоні з низьким рівнем інтересу в загальній сітці немає навіть 200 значень; між графічними межами x_minта x_maxі ще менше.

Тож для отримання гарної картини завдання полягає в тому, щоб отримати середнє значення за високими відсотковими значеннями та заповнити прогалини в інших місцях.

Я визначаю свою сітку зараз. Для кожної пари xx-yy я хочу мати колір.

xx = np.linspace(x_min, x_max, gridsize) # array of x values
yy = np.linspace(y_min, y_max, gridsize) # array of y values
grid = np.array(np.meshgrid(xx, yy.T))
grid = grid.reshape(2, grid.shape[1]*grid.shape[2]).T

Чому дивна форма? scipy.griddata хоче форму (n, D).

Griddata обчислює одне значення на точку в сітці заздалегідь визначеним методом. Я вибираю "найближчий" - порожні точки сітки заповняться значеннями від найближчого сусіда. Це виглядає так, ніби області з меншою кількістю інформації мають більші комірки (навіть якщо це не так). Можна було б інтерполювати "лінійні", тоді області з меншою кількістю інформації виглядають менш гостро. Справа смаку, дійсно.

points = np.array([x, y]).T # because griddata wants it that way
z_grid2 = griddata(points, z, grid, method='nearest')
# you get a 1D vector as result. Reshape to picture format!
z_grid2 = z_grid2.reshape(xx.shape[0], yy.shape[0])

І скакаємо, ми передаємо matplotlib для відображення сюжету

fig = plt.figure(1, figsize=(10, 10))
ax1 = fig.add_subplot(111)
ax1.imshow(z_grid2, extent=[x_min, x_max,y_min, y_max,  ],
            origin='lower', cmap=cm.magma)
ax1.set_title("SVC: empty spots filled by nearest neighbours")
ax1.set_xlabel('log gamma')
ax1.set_ylabel('log C')
plt.show()

Навколо точкової частини V-Shape ви бачите, що я зробив багато розрахунків під час пошуку солодкого місця, тоді як менш цікаві частини майже скрізь мають нижчу роздільну здатність.

Теплова карта SVC у високій роздільній здатності


Чи можете ви покращити свою відповідь, щоб мати повний і запущений код? Це цікавий метод, який ви надали. Я зараз намагаюся краще зрозуміти це. Я не зовсім розумію, чому існує також форма V. Дякую.
ldmtwo

V-Shape походить з моїх даних. Це значення f1 для навченого SVM: Це трохи піде в теорії SVM. Якщо у вас високий C, він враховує всі ваші бали в обчисленні, що дозволяє працювати ширшому гамма-діапазону. Гамма - це жорсткість кривої, що розділяє добро і погано. Ці два значення потрібно надати SVM (у моїй графіці X та Y); тоді ви отримуєте результат (Z у моїй графіці). У кращому районі ви сподіваєтесь, що до значних висот.
Андерас

друга спроба: V-Shape є в моїх даних. Це значення f1 для SVM: Якщо у вас високий C, він включає всі ваші бали в обчисленні, що дозволяє працювати більш широкому гамма-діапазону, але робить обчислення повільним. Гамма - це жорсткість кривої, що розділяє добро і погано. Ці два значення потрібно надати SVM (у моїй графіці X та Y); тоді ви отримуєте результат (Z у моїй графіці). В оптимізованій області ви отримуєте високі значення, в інших місцях низькі значення. Що я показав тут, можна використовувати, якщо у вас є Z-значення для деяких (X, Y) та багатьох прогалин в інших місцях. Якщо у вас є (X, Y, Z) точок даних, ви можете використовувати мій код.
Андера

4

Ось найкращий найближчий сусідський підхід Jurgy, але реалізований за допомогою scipy.cKDTree . У моїх тестах це приблизно в 100 разів швидше.

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

import numpy as np
import matplotlib.pyplot as plt
import matplotlib.cm as cm
from scipy.spatial import cKDTree


def data_coord2view_coord(p, resolution, pmin, pmax):
    dp = pmax - pmin
    dv = (p - pmin) / dp * resolution
    return dv


n = 1000
xs = np.random.randn(n)
ys = np.random.randn(n)

resolution = 250

extent = [np.min(xs), np.max(xs), np.min(ys), np.max(ys)]
xv = data_coord2view_coord(xs, resolution, extent[0], extent[1])
yv = data_coord2view_coord(ys, resolution, extent[2], extent[3])


def kNN2DDens(xv, yv, resolution, neighbours, dim=2):
    """
    """
    # Create the tree
    tree = cKDTree(np.array([xv, yv]).T)
    # Find the closest nnmax-1 neighbors (first entry is the point itself)
    grid = np.mgrid[0:resolution, 0:resolution].T.reshape(resolution**2, dim)
    dists = tree.query(grid, neighbours)
    # Inverse of the sum of distances to each grid point.
    inv_sum_dists = 1. / dists[0].sum(1)

    # Reshape
    im = inv_sum_dists.reshape(resolution, resolution)
    return im


fig, axes = plt.subplots(2, 2, figsize=(15, 15))
for ax, neighbours in zip(axes.flatten(), [0, 16, 32, 63]):

    if neighbours == 0:
        ax.plot(xs, ys, 'k.', markersize=5)
        ax.set_aspect('equal')
        ax.set_title("Scatter Plot")
    else:

        im = kNN2DDens(xv, yv, resolution, neighbours)

        ax.imshow(im, origin='lower', extent=extent, cmap=cm.Blues)
        ax.set_title("Smoothing over %d neighbours" % neighbours)
        ax.set_xlim(extent[0], extent[1])
        ax.set_ylim(extent[2], extent[3])

plt.savefig('new.png', dpi=150, bbox_inches='tight')

1
Я знав, що моя реалізація була дуже неефективною, але не знав про cKDTree. Молодці! Я посилаюся на вас у своїй відповіді.
Jurgy

2

Створіть двовимірний масив, який відповідає осередкам у вашому кінцевому зображенні, називається сказати heatmap_cellsта інстанціювати його як усі нулі.

Виберіть два коефіцієнти масштабування, які визначають різницю між кожним елементом масиву в реальних одиницях, для кожного виміру, скажімо, x_scaleі y_scale. Виберіть такі, щоб усі ваші точки даних потрапляли в межі масиву теплових карт.

Для кожної необробленої точки даних з x_valueта y_value:

heatmap_cells[floor(x_value/x_scale),floor(y_value/y_scale)]+=1


1

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

Ось я зробив набір на 1 мільйон точок з 3 категорій (кольоровий червоний, зелений та синій). Ось посилання на сховище, якщо ви хочете спробувати функцію. Github Repo

histplot(
    X,
    Y,
    labels,
    bins=2000,
    range=((-3,3),(-3,3)),
    normalize_each_label=True,
    colors = [
        [1,0,0],
        [0,1,0],
        [0,0,1]],
    gain=50)

0

Дуже схожа на відповідь @ Piti , але для отримання балів використовується 1 дзвінок замість 2:

import numpy as np
import matplotlib.pyplot as plt

pts = 1000000
mean = [0.0, 0.0]
cov = [[1.0,0.0],[0.0,1.0]]

x,y = np.random.multivariate_normal(mean, cov, pts).T
plt.hist2d(x, y, bins=50, cmap=plt.cm.jet)
plt.show()

Вихід:

2d_gaussian_heatmap


0

Боюся, я трохи запізнююсь на вечірку, але у мене було подібне запитання деякий час тому. Прийнята відповідь (від @ptomato) допомогла мені, але я також хотів би опублікувати це, якщо це комусь стане у нагоді.


''' I wanted to create a heatmap resembling a football pitch which would show the different actions performed '''

import numpy as np
import matplotlib.pyplot as plt
import random

#fixing random state for reproducibility
np.random.seed(1234324)

fig = plt.figure(12)
ax1 = fig.add_subplot(121)
ax2 = fig.add_subplot(122)

#Ratio of the pitch with respect to UEFA standards 
hmap= np.full((6, 10), 0)
#print(hmap)

xlist = np.random.uniform(low=0.0, high=100.0, size=(20))
ylist = np.random.uniform(low=0.0, high =100.0, size =(20))

#UEFA Pitch Standards are 105m x 68m
xlist = (xlist/100)*10.5
ylist = (ylist/100)*6.5

ax1.scatter(xlist,ylist)

#int of the co-ordinates to populate the array
xlist_int = xlist.astype (int)
ylist_int = ylist.astype (int)

#print(xlist_int, ylist_int)

for i, j in zip(xlist_int, ylist_int):
    #this populates the array according to the x,y co-ordinate values it encounters 
    hmap[j][i]= hmap[j][i] + 1   

#Reversing the rows is necessary 
hmap = hmap[::-1]

#print(hmap)
im = ax2.imshow(hmap)

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

Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.