Исправление галочек на цветовой полосе matplotlib

Я разместил цветную полосу рядом с картограммой. Поскольку отображаемые данные являются дискретными, а не непрерывными значениями, я использовал LinearSegmentedColormap (используя рецепт из кулинарная книга scipy), которую я инициализировал своим максимальным подсчитанным значением + 1, чтобы показать цвет для 0. Однако теперь у меня есть две проблемы:

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

  1. Метки галочки расположены неправильно (кроме 5, больше или меньше) — они должны быть расположены в середине цвета, который они определяют; т.е. 0 - 4 должны быть перемещены вверх, а 6 - 10 должны быть перемещены вниз.

  2. Если я инициализирую цветовую полосу с помощью drawedges=True, чтобы я мог стилизовать ее свойства dividers, я получаю следующее:

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

Я создаю свою цветовую карту и цветовую панель следующим образом:

cbmin, cbmax = min(counts), max(counts)
# this normalises the counts to a 0,1 interval
counts /= np.max(np.abs(counts), axis=0)
# density is a discrete number, so we have to use a discrete color ramp/bar
cm = cmap_discretize(plt.get_cmap('YlGnBu'), int(cbmax) + 1)
mappable = plt.cm.ScalarMappable(cmap=cm)
mappable.set_array(counts)
# set min and max values for the colour bar ticks
mappable.set_clim(cbmin, cbmax)
pc = PatchCollection(patches, match_original=True)
# impose our colour map onto the patch collection
pc.set_facecolor(cm(counts))
ax.add_collection(pc,)
cb = plt.colorbar(mappable, drawedges=True)

Поэтому мне интересно, является ли мое преобразование счетчиков в интервал 0,1 одной из проблем.

Обновлять :

Попробовав то, что предложил Хукед, значение 0 является правильным, но последующие значения устанавливаются постепенно выше, до точки, где 9 находится там, где должно быть 10:

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

Вот код, который я использовал:

cb = plt.colorbar(mappable)
labels = np.arange(0, int(cbmax) + 1, 1)
loc = labels + .5
cb.set_ticks(loc)
cb.set_ticklabels(labels)

И просто для подтверждения, labels определенно имеет правильные значения:

In [3]: np.arange(0, int(cbmax) + 1, 1)
Out[3]: array([ 0,  1,  2,  3,  4,  5,  6,  7,  8,  9, 10])

person urschrei    schedule 09.09.2013    source источник
comment
Похоже, проблема должна заключаться в цветовой полосе, которую вы, по сути, создаете вручную с помощью PatchCollection. Есть ли какая-либо причина не использовать линейную дискретную цветовую карту, такую ​​​​как страница scipy, на которую вы ссылаетесь?   -  person Hooked    schedule 10.09.2013
comment
Вы имеете в виду создать карту цветов, передать ее PatchCollection в качестве аргумента cmap, а затем pc.set_array в счетчики?   -  person urschrei    schedule 10.09.2013


Ответы (2)


Вы страдаете от ошибки off-by-one. У вас есть 10 меток, распределенных по 11 цветам. Возможно, вы сможете исправить ошибку, используя np.linspace вместо np.arange. Использование np.linspace в качестве третьего аргумента представляет собой количество желаемых значений. Это уменьшает количество умственной гимнастики, необходимой для того, чтобы избежать ошибки «один за другим»:

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

def colorbar_index(ncolors, cmap):
    cmap = cmap_discretize(cmap, ncolors)
    mappable = cm.ScalarMappable(cmap=cmap)
    mappable.set_array([])
    mappable.set_clim(-0.5, ncolors+0.5)
    colorbar = plt.colorbar(mappable)
    colorbar.set_ticks(np.linspace(0, ncolors, ncolors))
    colorbar.set_ticklabels(range(ncolors))

def cmap_discretize(cmap, N):
    """Return a discrete colormap from the continuous colormap cmap.

        cmap: colormap instance, eg. cm.jet. 
        N: number of colors.

    Example
        x = resize(arange(100), (5,100))
        djet = cmap_discretize(cm.jet, 5)
        imshow(x, cmap=djet)
    """

    if type(cmap) == str:
        cmap = plt.get_cmap(cmap)
    colors_i = np.concatenate((np.linspace(0, 1., N), (0.,0.,0.,0.)))
    colors_rgba = cmap(colors_i)
    indices = np.linspace(0, 1., N+1)
    cdict = {}
    for ki,key in enumerate(('red','green','blue')):
        cdict[key] = [ (indices[i], colors_rgba[i-1,ki], colors_rgba[i,ki])
                       for i in xrange(N+1) ]
    # Return colormap object.
    return mcolors.LinearSegmentedColormap(cmap.name + "_%d"%N, cdict, 1024)

fig, ax = plt.subplots()
A = np.random.random((10,10))*10
cmap = plt.get_cmap('YlGnBu')
ax.imshow(A, interpolation='nearest', cmap=cmap)
colorbar_index(ncolors=11, cmap=cmap)    
plt.show()

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

person unutbu    schedule 09.09.2013

Вы можете контролировать размещение и метки вручную. Я начну с линейной cmap, сгенерированной из cmap_discretize на странице, на которую вы ссылаетесь:

import numpy as np
import pylab as plt

# The number of divisions of the cmap we have
k = 10

# Random test data
A = np.random.random((10,10))*k
c = cmap_discretize('jet', k)

# First show without
plt.subplot(121)
plt.imshow(A,interpolation='nearest',cmap=c)
plt.colorbar()

# Now label properly
plt.subplot(122)
plt.imshow(A,interpolation='nearest',cmap=c)

cb = plt.colorbar()
labels = np.arange(0,k,1)
loc    = labels + .5
cb.set_ticks(loc)
cb.set_ticklabels(labels)

plt.show()

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

person Hooked    schedule 09.09.2013
comment
Хм, это все же не правильно, но по-другому. См. редактирование. - person urschrei; 09.09.2013