Как я могу указать список цветов для прямоугольников, используя patches.PathPatch? - PullRequest
0 голосов
/ 12 октября 2018

Я хочу составить график, состоящий из цветных прямоугольников, и в качестве ориентира использовал этот пример https://matplotlib.org/gallery/misc/histogram_path.html#sphx-glr-gallery-misc-histogram-path-py:

import numpy as np
import matplotlib.pyplot as plt
import matplotlib.patches as patches
import matplotlib.path as path

fig, ax = plt.subplots()

# Fixing random state for reproducibility
np.random.seed(19680801)

data = np.random.randn(1000)
n, bins = np.histogram(data, 50)

# get the corners of the rectangles for the histogram
left = np.array(bins[:-1])
right = np.array(bins[1:])
bottom = np.zeros(len(left))
top = bottom + n

XY = np.array([[left, left, right, right], [bottom, top, top, bottom]]).T

# get the Path object
barpath = path.Path.make_compound_path_from_polys(XY)

# make a patch out of it
patch = patches.PathPatch(barpath)
ax.add_patch(patch)

# update the view limits
ax.set_xlim(left[0], right[-1])
ax.set_ylim(bottom.min(), top.max())

plt.show()

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

patch=patches.PathPatch(barpath,fill=True,color=cols
,cmap='CMRmap')

Но я получаю "Invalid rgba arg", эта подпрограмма распознает только списки RGB?

Ответы [ 2 ]

0 голосов
/ 13 октября 2018

A matplotlib.patches.PathPatch имеет один цвет лица.Его нельзя по-разному раскрасить.Это упоминается в , например,

может более эффективно рисовать коллекции объектов правильной формы с однородными свойствами с помощью PathCollection.

Таким образом, мотивация использовать эту стратегию вместо создания обычной гистограммы и раскрасить ее столбцы - это эффективность.Немного менее эффективный способ создания гистограммы, но все же быстрее, чем обычный bars, - это использование PolyCollection.

Итак, давайте рассмотрим три различных решения ниже.

import numpy as np; np.random.seed(19680801)
import matplotlib.pyplot as plt
import matplotlib.patches as patches
import matplotlib.path as path
import matplotlib.collections
import matplotlib.cm

data = np.random.randn(1000)


def compoundpathhist(data, nbins=50):
    n, bins = np.histogram(data, nbins)
    # get the corners of the rectangles for the histogram
    left = np.array(bins[:-1])
    right = np.array(bins[1:])
    bottom = np.zeros(len(left))
    top = bottom + n


    # we need a (numrects x numsides x 2) numpy array for the path helper
    # function to build a compound path
    XY = np.array([[left, left, right, right], [bottom, top, top, bottom]]).T

    # get the Path object
    barpath = path.Path.make_compound_path_from_polys(XY)

    # make a patch out of it
    patch = patches.PathPatch(barpath)
    fig, ax = plt.subplots()
    ax.add_patch(patch)
    # update the view limits
    ax.set_xlim(left[0], right[-1])
    ax.set_ylim(bottom.min(), top.max())

    fig.savefig("bartest.png")


def polyhist(data, nbins=50, colors=True):
    n, bins = np.histogram(data, nbins)
    # get the corners of the rectangles for the histogram
    left = np.array(bins[:-1])
    right = np.array(bins[1:])
    bottom = np.zeros(len(left))
    top = bottom + n
    # we need a (numrects x numsides x 2) numpy array to be used as 
    # vertices for the PolyCollection
    XY = np.array([[left, left, right, right], [bottom, top, top, bottom]]).T

    c=None
    if colors:
        c = matplotlib.cm.RdYlBu(n/n.max())
    pc = matplotlib.collections.PolyCollection(XY, facecolors=c)

    fig, ax = plt.subplots()
    ax.add_collection(pc)
    # update the view limits
    ax.set_xlim(left[0], right[-1])
    ax.set_ylim(bottom.min(), top.max())

    fig.savefig("bartest.png")



def hist_c(data, nbins=50, colors=True):

    fig, ax = plt.subplots()
    n, bins, patches = ax.hist(data, nbins)

    if colors:
        cols = matplotlib.cm.RdYlBu(n/n.max())
        for p,c in zip(patches, cols):
            p.set_facecolor(c)

    # update the view limits
    ax.set_xlim(bins.min(), bins.max())
    ax.set_ylim(n.min(), n.max())

    fig.savefig("bartest.png")


compoundpathhist(data, nbins=50)
polyhist(data, nbins=50)
hist_c(data, nbins=50, colors=True)

plt.show()

enter image description here

  • Первый (compoundpathhist) - тот из связанного примера.Это быстро, но не может показать цвет.
  • Второй (polyhist) не использует ни одного патча, а вместо него PolyCollection.Цвет лица PolyCollection можно установить с помощью карты цветов.
  • Третье (hist_c) - это адаптированное обычное решение для раскрашивания отдельных полос.

Теперь мы можем синхронизировать три функции.Я использую 90000 точек данных и 50, 500 и 5000 бинов.

enter image description here

Мы наблюдаем, что для обычного числа бинов ~ 50, по существу, нет никакой разницы между этими методами.Однако для большего количества ячеек метод hist занимает значительно больше времени.Даже для 5000 бинов почти нет разницы между методом compoundpathhist (который не может использовать цвет) и polyhist, который может использовать цвет.Следовательно, это полезная альтернатива без ущерба для эффективности.Между прочим, почти нет разницы между использованием цвета или не использованием цвета в соответствующих функциях.

0 голосов
/ 12 октября 2018

Я думаю, что вы идете по более длинному ненужному маршруту, чтобы покрасить каждую полосу по-разному.Просто используйте следующий (более короткий) подход.Использование PathPatch и Path вообще не требуется.Вы можете удалить edgecolor='black', если вам не нужны черные края.

Объяснение : получить patches объект непосредственно из plt.hist.Затем создайте список цветов на основе карты цветов CMRmap.Наконец зациклите patches и установите цвет каждого патча.

import numpy as np
import matplotlib.pyplot as plt

fig, ax = plt.subplots()

# Fixing random state for reproducibility
np.random.seed(19680801)

data = np.random.randn(1000)
N, bins, patches = plt.hist(data, bins=50, edgecolor='black')

cm = plt.get_cmap('CMRmap')
for i in range(len(patches)):
    color = cm(1.*i/len(patches))  
    patches[i].set_facecolor(color)

enter image description here

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...