Как сделать matshow или imshow, но отобразить значения осей в виде границ бина (то есть, как на графике 2d частота / плотность) - PullRequest
0 голосов
/ 25 февраля 2019

Мне нужно сделать двухмерный плотоподобный график.Однако я сам вычисляю «плотности».По сути, у меня есть массив значений NxM, которые я могу отображать только с помощью plt.matshow (или imshow).

fig, ax = plt.subplots()
im = ax.matshow(value_array)
ax.set_xticklabels(x_edges - 2.5)
ax.set_yticklabels(y_edges - 0.25)

Однако в этом случае значения осей являются пикселями на графике,тогда как я действительно хочу, чтобы он показывал некоторые пользовательские значения.Поэтому я вручную изменяю метки галочек, как указано выше.

Это все еще оставляет проблему.matshow по-прежнему считает, что метки галочек обозначают «пиксели» на изображении, поэтому метки галочек печатаются в «середине» каждого квадрата пикселей.Однако, как я уже сказал, то, что я на самом деле пытаюсь построить, больше похоже на график плотности, поэтому каждый «квадрат пикселей» представляет собой ячейку в пространстве x, y.Было бы намного разумнее иметь метки для отметок на квадратных углах, как это делается для графиков гистограммы и частотных графиков в целом.

Стоит ли продолжать использовать matshow дляэто или есть другая функция, которая делает это?Например, могу ли я использовать plt.hist2d, но вручную устанавливать «высоту», не вводя данные в виде набора сэмплов?Иначе, как я могу заставить plt.matshow ставить метки галочек так, как я хочу?

Ответы [ 2 ]

0 голосов
/ 26 февраля 2019

В дополнение к ответу @TomdeGeus, здесь есть кое-что, что может помочь.Поскольку мне нужно было нарисовать фигуру, где ось Y растягивается от 0,5 до 3,5, а ось X растягивается от 0 до 40, она была очень сжатой на изображении, и мне, возможно, пришлось форсировать соотношение сторон, которое не былот работает.Также было что-то не так с отображаемыми галочками.

Однако после исправления соотношения сторон, я определенно рекомендую вам следовать ответу Тома де Жеуса, это правильный способ сделать это.

Таким образом, я по-прежнему строю изображение в «пиксельных» координатах, т.е. выбираю экстент так, чтобы оси x и y подсчитывали пиксели, но начинались с 0, а не с -0,5, как поведение по умолчанию plt.imshow()

fig, ax = plt.subplots()

im = ax.matshow(value_grid, origin='lower', extent=(0, len(x_edges)-1, 0, len(y_edges)-1)

Где len(y_edges) - 1 подсчитывает количество пикселей, которые я хочу на оси Y (а y_edges - список, содержащий значения границ ячейки, которые я хочу отобразить на оси Yкак и раньше.

Затем я вручную заменяю метки тиков, но мне также нужно правильно сопоставить их с правильными тиками.

ax.set_xticks(list(range(len(x_edges))))
ax.set_xticklabels(x_edges)
ax.set_yticks(list(range(len(y_edges))))
ax.set_yticklabels(y_edges)

Это сохраняет квадратный характер пикселей, создаваемых imshow, однако вы должны иметь в виду, что базовая ось по-прежнему определяется в пикселях (т. Е. Если я хочу разместить точку на координате (25.0, 2.0), она фактически не будет выглядеть каквверх в этом месте.

enter image description here

0 голосов
/ 25 февраля 2019

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

На самом деле вы можете использовать комбинацию numpy.histogram2d и matplotlib.pyplot.imshow.

Позвольте мне начать с предупреждения.С imshow вы отображаете пиксели.Следовательно, вы подразумеваете, что ячейки имеют одинаковый размер по каждой оси.Они могут иметь различную ширину и высоту, но ширина / высота каждого бина должна быть одинаковой, чтобы представление было справедливым.как это:

import matplotlib.pyplot as plt
import numpy as np

N = 100000
x = np.random.randn(N)
y = np.random.weibull(2.,N)

P, xedges, yedges = np.histogram2d(x, y, bins=(np.linspace(-4,+5,10), np.linspace(0,4,21)), density=True)

fig, ax = plt.subplots()

cax = ax.imshow(P.T, extent=(xedges[0], xedges[-1], yedges[0], yedges[-1]),
  origin='lower', interpolation='nearest', clim=(0,.4), cmap='afmhot_r')

cbar = fig.colorbar(cax,aspect=10)

ax.set_aspect('auto')

ax.set_xlabel('x')
ax.set_ylabel('y')

plt.savefig('test.png')
plt.show()

Какие графики

enter image description here

Хитрая часть заключается в том, чтобы получить естественный вывод:

  • Вы должны перезаписать imshow по умолчанию, указав начало координат верхней части изображения.Как указано, это делается с помощью опции origin='lower'.
  • Вы должны построить транспонированный вывод numpy.histogram, потому что imshow показывает матрицу как есть, а вывод numpy.histogram показываетимеет форму (nx, ny): значения по оси X соответствуют строкам.
  • Возможно, вам придется изменить соотношение сторон, см. этот ответ .
...