matplotlib hexbin нормализовать

Я хотел бы создать карту плотности данных x y с несколькими шестнадцатеричными бинами с помощью matplotlib, аналогичную этой: http://matplotlib.org/1.4.0/examples/pylab_examples/hexbin_demo.html

Но я хотел бы разделить количество на шестиугольник на заданное число (самое высокое значение пика из моих карт плотности), чтобы все мои графики плотности имели одинаковую окраску, а цветовая полоса была бы в диапазоне [0,1] для всех графиков. .

Может ли кто-нибудь показать мне рабочий пример этого?

Спасибо в ожидании,

Янош


person user2393987    schedule 31.03.2015    source источник


Ответы (2)


Я вижу два возможных способа сделать это.

Способ 1

Первый — вызвать hexbin, чтобы получить максимальное значение, а затем выполнить еще один вызов hexbin, используя параметр ввода reduce_C_function для масштабирования ваших данных. Проблема с выполнением нормализации заключается в том, что вы не знаете, сколько точек находится в каждом бине, пока не будет создан шестнадцатеричный бин. Работая с данными в примере, на который вы ссылаетесь (но только создавая график линейного масштаба), это будет примерно так:

plt.subplot(111)
hb = plt.hexbin(x,y, cmap=plt.cm.YlOrRd_r)
plt.cla()
plt.hexbin(x, y,
           C=np.ones_like(y, dtype=np.float) / hb.get_array().max(),
           cmap=plt.cm.YlOrRd_r,
           reduce_C_function=np.sum)
plt.axis([xmin, xmax, ymin, ymax])
cb = plt.colorbar()

Во втором вызове hexbin вы должны указать массив C, чтобы использовать опцию reduce_C_function. В этом случае C=np.ones_like(y) / hb.get_array().max() — это все, что вам нужно, потому что вы просто суммируете значения.

Обратите внимание, что, вероятно, имеет смысл очищать оси после первого вызова hexbin.

Одна проблема с этим подходом заключается в том, что у вас будут пустые ячейки (пробелы), где нет точек. Если вы хотите, чтобы фон был того же цвета, что и нулевое значение, вы можете добавить plt.gca().set_axis_bgcolor(plt.cm.YlOrRd_r(0)).

Способ 2

Другой подход состоит в том, чтобы просто использовать автоматическое масштабирование, присущее hexbin, и просто переименовать цветовую полосу. Например:

plt.subplot(111)
hb = plt.hexbin(x,y, cmap=plt.cm.YlOrRd_r)
plt.axis([xmin, xmax, ymin, ymax])
cb = plt.colorbar()
cb.set_ticks(np.linspace(hb.get_array().min(), hb.get_array().max(), 6))
cb.set_ticklabels(np.linspace(0, 1., 6))

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

person farenorth    schedule 31.03.2015
comment
Отличные решения с очень дидактическим объяснением. Спасибо Фаренорт! Одна часть, которую я пропустил в своих предыдущих попытках, — это часть reduce_C_function=np.sum. Не могли бы вы объяснить мне, что делает функция reduce_C_function? Спасибо еще раз! Янош - person user2393987; 31.03.2015
comment
Он применяется к значениям, найденным в каждом бине, для вычисления одного значения, которое затем представляется в виде цвета. Найдите «reduce_C_function» здесь: matplotlib.org/api/pyplot_api.html для получения более подробной информации. - person farenorth; 31.03.2015

Метод 2 @farenorth очень хорош. Вместо этого можно использовать следующее, чтобы получить график плотности шестигранника:

cb.set_ticks(np.linspace(hb.get_array().min(), hb.get_array().max(), 6))
cb.set_ticklabels(['%.4f'%x for x in np.linspace(hb.get_array().min()/hb.get_array().sum(), hb.get_array().max()/hb.get_array().sum(), 6)])
person tgm    schedule 01.03.2019