У меня есть набор точек данных X, Y (около 10 тыс.), Которые легко построить в виде точечной диаграммы, но которые я хотел бы представить в виде тепловой карты.
Я просмотрел примеры в MatPlotLib, и все они, похоже, уже начинаются со значений ячеек тепловой карты для генерации изображения.
Есть ли метод, который преобразует группу x, y, все разные, в тепловую карту (где зоны с более высокой частотой x, y будут «теплее»)?
Ответы:
Если вам не нужны шестиугольники, вы можете использовать
histogram2d
функцию numpy :Это составляет тепловую карту 50x50. Если вы хотите, скажем, 512x384, вы можете
bins=(512, 384)
позвонить наhistogram2d
.Пример:
источник
axes
экземпляр, в котором я могу добавить заголовок, метки оси и т. Д., А затем выполнить нормальный режим,savefig()
как я сделал бы для любого другого типичного сюжета matplotlib.plt.savefig('filename.png')
работает? Если вы хотите получить экземпляр оси, используйте объектно-ориентированный интерфейс Matplotlib:fig = plt.figure()
ax = fig.gca()
ax.imshow(...)
fig.savefig(...)
imshow()
это та же категория функций, что иscatter()
. Я, честно говоря, не понимаю, почемуimshow()
преобразует двумерный массив с плавающей точкой в блоки соответствующего цвета, тогда как я понимаю, чтоscatter()
делать с таким массивом.plt.imshow(heatmap.T, extent=extent, origin = 'lower')
from matplotlib.colors import LogNorm
plt.imshow(heatmap, norm=LogNorm())
plt.colorbar()
В лексиконе Matplotlib , я думаю, вы хотите сюжет в гексбине .
Если вы не знакомы с этим типом графика, это просто двумерная гистограмма, в которой плоскость xy тесселяется регулярной сеткой шестиугольников.
Таким образом, из гистограммы вы можете просто подсчитать количество точек, попадающих в каждый шестиугольник, дискретизировать область построения как набор окон , назначить каждую точку одному из этих окон; наконец, сопоставьте окна с массивом цветов , и у вас получится шестнадцатеричная диаграмма.
Хотя они используются реже, чем, например, круги или квадраты, эти шестиугольники являются лучшим выбором для геометрии контейнера для сбора мусора, интуитивно понятны:
шестиугольники имеют симметрию ближайшего соседа (например, квадратные ячейки не имеют, например, расстояние от точки на границе квадрата до точки внутри этого квадрата не везде одинаково) и
шестиугольник - это самый высокий n-многоугольник, который дает регулярную плоскую тесселяцию (т. е. вы можете смело смоделировать пол на кухне плитками шестиугольной формы, потому что у вас не будет пустого пространства между плитками, когда вы закончите - это не так все остальные высшие n, n> = 7, полигоны).
( Matplotlib использует термин hexbin plot; так же (AFAIK) - все библиотеки построения графиков для R ; все еще я не знаю, является ли это общепринятым термином для графиков этого типа, хотя я подозреваю, что, вероятно, учитывая, что hexbin является коротким для гексагонального биннинга , который описывает важный шаг при подготовке данных для отображения.)
источник
gridsize=
параметр. Я хотел бы выбрать его таким, чтобы шестиугольники просто соприкасались, не перекрывая друг друга. Я заметил, чтоgridsize=100
будет производить меньшие шестиугольники, но как выбрать правильное значение?Изменить: Для лучшего приближения ответа Алехандро, см. Ниже.
Я знаю, что это старый вопрос, но я хотел добавить кое-что к ответу Алехандро: если вы хотите получить хорошее сглаженное изображение без использования py-sphviewer, вы можете вместо этого использовать
np.histogram2d
и применить гауссов фильтр (сscipy.ndimage.filters
) к тепловой карте :Производит:
Диаграмма рассеивания и s = 16, нанесенные поверх друг друга для Агапе Гальо (нажмите для лучшего просмотра):
Одно отличие, которое я заметил с моим подходом гауссовского фильтра и подходом Алехандро, было то, что его метод показывает локальные структуры намного лучше, чем мой. Поэтому я реализовал простой метод ближайшего соседа на уровне пикселей. Этот метод рассчитывает для каждого пикселя обратную сумму расстояний
n
ближайших точек в данных. Этот метод с высоким разрешением довольно затратен в вычислительном отношении, и я думаю, что есть более быстрый способ, поэтому дайте мне знать, если у вас есть какие-либо улучшения.Обновление: как я и подозревал, есть гораздо более быстрый метод с использованием Сципи
scipy.cKDTree
. Смотрите ответ Габриэля для реализации.Во всяком случае, вот мой код:
Результат:
источник
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
.Вместо того, чтобы использовать np.hist2d, который обычно генерирует довольно некрасивые гистограммы, я хотел бы переработать py-sphviewer , пакет python для рендеринга симуляций частиц с использованием адаптивного сглаживающего ядра, который можно легко установить из pip (см. Документацию веб-страницы). Рассмотрим следующий код, основанный на примере:
который производит следующее изображение:
Как видите, изображения выглядят довольно красиво, и мы можем определить различные подструктуры на нем. Эти изображения построены с распределением заданного веса для каждой точки в определенной области, определенной длиной сглаживания, которая, в свою очередь, определяется расстоянием до ближайшего соседа nb (в качестве примеров я выбрал 16, 32 и 64). Таким образом, области с более высокой плотностью обычно распространяются на более мелкие области по сравнению с областями с более низкой плотностью.
Функция myplot - это просто очень простая функция, которую я написал для того, чтобы передать данные x, y py-sphviewer для выполнения магии.
источник
Если вы используете 1.2.x
источник
У Seaborn теперь есть функция jointplot, которая должна хорошо работать здесь:
источник
fig = plt.figure(figsize=(12, 12))
, затем получите текущую ось сax=plt.gca()
, затем добавьте аргументax=ax
вjointplot
функцию.и первоначальный вопрос был ... как преобразовать значения разброса в значения сетки, верно?
histogram2d
действительно рассчитывает частоту на ячейку, однако, если у вас есть данные на ячейку, отличные от частоты, вам потребуется дополнительная работа.Итак, у меня есть набор данных с Z-результатами для координат X и Y. Однако я вычислял несколько точек за пределами области интереса (большие пробелы) и кучу точек в небольшой области интереса.
Да, здесь становится сложнее, но и веселее. Некоторые библиотеки (извините):
Сегодня pyplot - мой графический движок, cm - это диапазон цветовых карт с некоторым интересным выбором. numpy для расчетов и griddata для привязки значений к фиксированной сетке.
Последнее важно, особенно потому, что частота точек xy не одинаково распределена в моих данных. Во-первых, давайте начнем с некоторых границ, подходящих для моих данных и произвольного размера сетки. Исходные данные также имеют точки данных вне этих границ x и y.
Итак, мы определили сетку с 500 пикселями между минимальным и максимальным значениями x и y.
По моим данным, существует более 500 доступных значений в области повышенного интереса; в то время как в области низкого интереса нет даже 200 значений в общей сетке; между графическими границами
x_min
иx_max
есть еще меньше.Таким образом, для получения хорошей картины задача состоит в том, чтобы получить среднее значение для высоких процентных значений и заполнить пробелы в других местах.
Я сейчас определяю свою сетку. Для каждой пары хх-уу я хочу иметь цвет.
Почему странная форма? scipy.griddata хочет иметь форму (n, D).
Griddata вычисляет одно значение для каждой точки в сетке с помощью предварительно определенного метода. Я выбираю «ближайший» - пустые точки сетки будут заполнены значениями от ближайшего соседа. Это выглядит так, как будто области с меньшим количеством информации имеют большие ячейки (даже если это не так). Можно выбрать интерполяцию «линейно», тогда области с меньшим количеством информации выглядят менее четкими. Дело вкуса, правда.
И хоп, мы передаем Matplotlib для отображения сюжета
Вокруг заостренной части V-образной формы вы видите, что я провел много вычислений во время поиска точки обзора, в то время как менее интересные детали почти везде имеют более низкое разрешение.
источник
Вот замечательный подход Jurgy для ближайшего соседа, но реализованный с использованием scipy.cKDTree . В моих тестах это примерно в 100 раз быстрее.
источник
Создайте 2-мерный массив, который соответствует ячейкам в вашем конечном изображении, с именем say
heatmap_cells
и создайте его экземпляр как все нули.Выберите два коэффициента масштабирования, которые определяют разницу между каждым элементом массива в реальных единицах, для каждого измерения, скажем,
x_scale
иy_scale
. Выберите их так, чтобы все ваши точки данных попадали в границы массива тепловых карт.Для каждого необработанного datapoint с
x_value
иy_value
:heatmap_cells[floor(x_value/x_scale),floor(y_value/y_scale)]+=1
источник
Вот один, который я сделал на наборе очков 1 миллион с 3 категориями (красный, зеленый и синий цвета). Вот ссылка на репозиторий, если вы хотите попробовать эту функцию. Github Repo
источник
Очень похоже на ответ @ Piti , но использует 1 вызов вместо 2 для генерации очков:
Вывод:
источник
Боюсь, я немного опоздал на вечеринку, но у меня был похожий вопрос некоторое время назад. Принятый ответ (@ptomato) помог мне, но я также хотел бы опубликовать его на тот случай, если он кому-нибудь пригодится.
Вот результат
источник