Python Matplotlib — imshow, но с шестиугольниками

Код:

import numpy as np
import matplotlib.pyplot as plt
from matplotlib import colors

example_data = np.random.randint(4, size=(40,44))
cmap = colors.ListedColormap(['black', 'green', 'red', 'blue'])
bounds = [0,1,2,3,4]
norm = colors.BoundaryNorm(bounds, cmap.N)

img = plt.imshow(example_data, interpolation = 'nearest', origin = 'lower',
cmap = cmap, norm = norm)

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

Спасибо.


person BloodSexMagik    schedule 20.07.2016    source источник
comment
И как бы вы определили свою шестиугольную мозаику из квадратной мозаики (вашего массива), которая у вас есть? Это звучит слишком специфично, чтобы иметь встроенную функцию. Я могу ошибаться, но я думаю, что вам нужно создать свою собственную процедуру построения графика...   -  person Julien    schedule 20.07.2016
comment
Боюсь, я еще не знаком с ним, но вы можете посмотреть на bokeh. Он имеет некоторую поддержку построения шестиугольных сеток.   -  person FChm    schedule 11.03.2019


Ответы (1)


Кто продолжает голосовать против этого без комментариев! Хотя предыдущая попытка (ниже) была прекрасным решением. Тем не менее, я понимаю, что это не очень хорошо мозаично, а шестиугольники имеют плохую форму. Вот лучшее решение с использованием патчей:

import numpy as np
import matplotlib.pyplot as plt
from matplotlib import colors
import matplotlib.patches as mpatches
from matplotlib.collections import PatchCollection

nx = 40
ny = 44
example_data = np.random.randint(4, size=(nx,ny))
cmap = colors.ListedColormap(['black', 'green', 'red', 'blue'])
bounds = [0,1,2,3,4]
norm = colors.BoundaryNorm(bounds, cmap.N)

x = np.linspace(0, 1, nx)
y = np.linspace(0, 1, ny)
X, Y = np.meshgrid(x, y)

dx = np.diff(x)[0]
dy = np.diff(y)[0]
ds = np.sqrt(dx**2 +  dy**2)

patches = []
for i in x:
    for n, j in enumerate(y):
        if n%2:
            polygon = mpatches.RegularPolygon([i-dx/2., j], 6, 0.6*dx)
        else:
            polygon = mpatches.RegularPolygon([i, j], 6, 0.6*dx)
        patches.append(polygon)

collection = PatchCollection(patches, cmap=cmap, norm=norm, alpha=1.0)

fig, ax = plt.subplots(1,1)
ax.add_collection(collection)
collection.set_array(example_data.ravel())
plt.show()

который выглядит так,

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

Предыдущее решение:

Вы можете использовать точечную диаграмму с цветными шестиугольниками,

import numpy as np
import matplotlib.pyplot as plt
from matplotlib import colors

nx = 40
ny = 44
example_data = np.random.randint(4, size=(nx,ny))
cmap = colors.ListedColormap(['black', 'green', 'red', 'blue'])
bounds = [0,1,2,3,4]
norm = colors.BoundaryNorm(bounds, cmap.N)

x = np.linspace(0, 1, nx)
y = np.linspace(0, 1, ny)
X, Y = np.meshgrid(x, y)

img = plt.scatter(X.ravel(),Y.ravel(),c=example_data.ravel(), cmap=cmap, norm=norm, s=360, marker=(6, 0), alpha=0.4)

plt.colorbar(img)
plt.show()

что похоже,

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

person Ed Smith    schedule 20.07.2016