Создание тепловой карты в MatPlotLib с использованием набора данных разброса
-
24-09-2019 - |
Вопрос
У меня есть набор точек данных X, Y (около 10 тыс.), которые легко построить как диаграмму рассеяния, но которые я хотел бы представить как тепловую карту.
Я просмотрел примеры в MatPlotLib, и все они, кажется, уже начинаются со значений ячеек тепловой карты для создания изображения.
Есть ли метод, который преобразует набор x, y, все разные, в тепловую карту (где зоны с более высокой частотой x, y будут «теплее»)?
Решение
Если вам не нужны шестиугольники, вы можете использовать функцию numpy histogram2d
:
Таким образом получается тепловая карта 50 x 50.Если вы хотите, скажем, 512x384, вы можете поместить bins=(512, 384)
в вызов histogram2d
.
Пример:
Другие советы
В лексиконе Matplotlib я думаю, вам нужен график hexbin .
Если вы не знакомы с этим типом графика, это просто двумерная гистограмма , в которой плоскость xy разбита на мозаику с помощью правильной сетки из шестиугольников.
Итак, по гистограмме вы можете просто подсчитать количество точек, попадающих в каждый шестиугольник, дискретизировать область построения как набор окон , назначить каждую точку одному из этих окон; наконец, сопоставьте окна с цветовым массивом , и вы получите шестнадцатеричную диаграмму.
Хотя шестиугольники используются реже, чем, например, круги или квадраты, они являются лучшим выбором для геометрии контейнера биннинга:
-
шестиугольники обладают симметрией ближайшего соседа (например, квадратные ячейки не имеют например, расстояние от точки на границе квадрата до точки внутри этого квадрата не везде одинаковы) и
-
шестиугольник - это наивысший n-многоугольник, который дает правильную плоскость. тесселяция (т. е. вы можете смоделировать пол на кухне с помощью плиток шестиугольной формы, потому что у вас не будет пустого пространства между плитками, когда вы закончите - это не верно для всех других значений с более высокими n, n >= 7, полигоны).
( Matplotlib использует термин hexbin plot; так (AFAIK) все библиотеки графиков для R ; все же я не Не знаю, является ли это общепринятым термином для графиков этого типа, хотя я подозреваю, что это вероятно, учитывая, что hexbin - это сокращение от гексагонального разбиения , которое описывает важный шаг при подготовке данных к отображению.)
родовое слово
Вместо использования np.hist2d, который обычно создает довольно уродливые гистограммы, я хотел бы переработать py-sphviewer , пакет Python для рендеринга моделирования частиц с использованием ядра адаптивного сглаживания, который можно легко установить из pip (см. документацию на веб-странице). Рассмотрим следующий код, основанный на примере:
родовое словов результате получается следующее изображение:
Как видите, изображения выглядят довольно красиво, и мы можем идентифицировать на них различные подструктуры. Эти изображения создаются с распределением заданного веса для каждой точки в определенной области, определяемой длиной сглаживания, которая, в свою очередь, определяется расстоянием до ближайшего соседа nb (я выбрал 16, 32 и 64 для примеров). Таким образом, области с более высокой плотностью обычно распределяются по более мелким областям по сравнению с областями с более низкой плотностью.
Функция myplot - это очень простая функция, которую я написал для того, чтобы передать данные x, y в py-sphviewer, чтобы он творил чудеса.
Если вы используете 1.2.x
родовое слово
Изменить: для лучшего приближения к ответу Алехандро см. ниже.
Я знаю, что это старый вопрос, но хотел добавить кое-что к ответу Алехандро: если вам нужно красивое сглаженное изображение без использования py-sphviewer, вы можете вместо этого использовать np.histogram2d
и применить фильтр Гаусса (из scipy.ndimage.filters
) к тепловой карте:
Производит:
Диаграмма рассеяния и s= 16, нанесенные поверх друг друга для Агапе Гальо (щелкните для лучшего обзора):
Одно отличие, которое я заметил в моем подходе к гауссовскому фильтру и подходу Алехандро, заключалось в том, что его метод показывает локальные структуры намного лучше, чем мой. Поэтому я реализовал простой метод ближайшего соседа на уровне пикселей. Этот метод вычисляет для каждого пикселя обратную сумму расстояний до ближайших точек кода кодового тега в данных. Этот метод с высоким разрешением довольно затратен с точки зрения вычислений, и я думаю, что есть более быстрый способ, поэтому дайте мне знать, если у вас есть какие-либо улучшения. Во всяком случае, вот код:
родовое словоРезультат:
У Seaborn теперь есть функция Jointplot , которая здесь должна хорошо работать:
родовое слово и первоначальный вопрос был ... как преобразовать значения разброса в значения сетки, верно?
histogram2d
подсчитывает частоту для каждой ячейки, однако, если у вас есть другие данные для каждой ячейки, кроме частоты, вам потребуется дополнительная работа.
Итак, у меня есть набор данных с Z-результатами для координат X и Y. Однако я вычислял несколько точек за пределами интересующей области (большие промежутки) и множество точек в небольшой интересующей области.
Да, здесь становится сложнее, но и веселее. Некоторые библиотеки (извините):
родовое словоPyplot - это мой графический движок сегодня, cm - это набор цветных карт с интересным выбором. numpy для расчетов, и griddata для привязки значений к фиксированной сетке.
Последнее важно, особенно потому, что частота точек xy неравномерно распределена в моих данных. Во-первых, давайте начнем с некоторых границ, соответствующих моим данным, и произвольного размера сетки. Исходные данные имеют точки данных также за пределами этих границ x и y.
родовое словоИтак, мы определили сетку с 500 пикселями между минимальным и максимальным значениями x и y.
По моим данным, в наиболее интересной области доступно намного больше 500 значений; тогда как в области с низким процентом в общей сетке нет даже 200 значений; Между графическими границами x_min
и x_max
еще меньше.
Итак, чтобы получить хорошую картину, задача состоит в том, чтобы получить среднее значение для высоких значений интереса и заполнить пробелы в других местах.
Сейчас я определяю свою сетку. Для каждой пары xx-yy я хочу иметь цвет.
родовое словоПочему странная форма? scipy.griddata хочет форма (n, D).
Griddata рассчитывает одно значение для каждой точки в сетке заранее определенным методом. Выбираю «ближайший» - пустые точки сетки будут заполнены значениями от ближайшего соседа. Это выглядит так, как будто области с меньшим количеством информации имеют более крупные ячейки (даже если это не так). Можно выбрать «линейную» интерполяцию, тогда области с меньшим количеством информации будут выглядеть менее резкими. Дело вкуса, правда.
родовое словоИ мы передаем команду matplotlib для отображения графика
родовое словоВокруг заостренной части V-образной формы, как видите, я проделал много вычислений во время поиска золотого пятна, тогда как менее интересные части почти везде имеют более низкое разрешение.
Создайте двумерный массив, который соответствует ячейкам на вашем окончательном изображении, назовите, скажем, heatmap_cells
, и создайте его как все нули.
Выберите два масштабных коэффициента, которые определяют разницу между каждым элементом массива в реальных единицах измерения для каждого измерения, например, x_scale
и y_scale
.Выберите их так, чтобы все ваши точки данных попадали в границы массива тепловой карты.
Для каждой необработанной точки данных с общим кодом кода и кодом кода:
x_value
Очень похоже на ответ @ Piti , но для генерации баллов используется 1 вызов вместо 2:
родовое словоВывод:
Вот один, который я сделал на наборе в 1 миллион точек с 3 категориями (красный, зеленый и синий).Вот ссылка на репозиторий, если вы хотите попробовать эту функцию. Github Repo
родовое слово