python - Matplotlib:在 hexbin 图中使用最频繁值的 bin 组添加边框

标签 python matplotlib

我正在使用以下 Python 脚本制作一个 hexbin 图:

pitch = Pitch(
    line_color="#747474", pitch_color="#222222", orientation="vertical", half=True, plot_arrow=False
)

fig, ax = pitch.create_pitch()

## color-map
cmap = [
    "#222222", "#3A2527", "#52282B", "#6A2B30", 
    "#762C32", "#822D34", "#8E2F37", "#9A3039", 
    "#B2323D", "#BE3440", "#CA3542", "#E13746"
]
cmap = colors.ListedColormap(cmap)

hexbin = ax.hexbin(
    68 - shots_data['Y'], shots_data['X'], zorder=3, cmap=cmap,
    extent=(0, 68, 52, 104), gridsize=22, bins=13, ec="#222222", lw=3
)
上面的代码产生以下输出:
enter image description here
现在我想用最频繁的值在六边形周围添加边框,看起来像这样。请注意,在下图中,白色边框是手绘的,以显示结果的外观。我不知道该怎么做。我应该在代码中添加什么来产生这样的结果。
enter image description here
编辑:
我得到了一些结果,但它们并不完美,这是更新后的脚本:
## Pitch obejct
pitch = Pitch(
    line_color="#747474", pitch_color="#222222", orientation="vertical", half=True, plot_arrow=False
)

## create-pitch
fig, ax = pitch.create_pitch()

## colormap
cmap = [
    "#3A2527", "#52282B", "#6A2B30", "#822D34",
    "#822D34","#882E36", "#8E2F37", "#9A3039", "#B2323D", "#E13746"
]
cmap = colors.ListedColormap(cmap)

## extent
extent = (
    shots_data['Y'].min(), shots_data['Y'].max(),
    shots_data['X'].min(), shots_data['X'].max(),
)

## main hexbin
hexbin = ax.hexbin(
    68 - shots_data['Y'], shots_data['X'], zorder=3, cmap=cmap,
    extent=extent, gridsize=22, ec="#222222", lw=1, bins="log", mincnt=1
)

## hexbin with mincnt=6
cmap = [
     "#822D34", "#882E36", "#8E2F37", "#9A3039", "#B2323D", "#E13746"
]
cmap = colors.ListedColormap(cmap)
ax.hexbin(
    68 - shots_data['Y'], shots_data['X'], zorder=3, cmap=cmap,
    extent=extent, gridsize=22, ec="#bce7ef", lw=1, bins="log", mincnt=6
)


## add rectangle 
rect = plt.Rectangle(
    xy=(-0.1, 104), width=68.1, height=1, zorder=3, fc="#222222"
)
ax.add_patch(rect)
这产生了以下结果:
enter image description here

最佳答案

我制定了两个版本来绘制六边形的轮廓线。
(标题)

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

# color-map
cmap = [ "#222222", "#3A2527", "#52282B", "#6A2B30", "#762C32", "#822D34", 
        "#8E2F37", "#9A3039", "#B2323D", "#BE3440", "#CA3542", "#E13746"]
cmap = matplotlib.colors.ListedColormap(cmap)

#prepare data
np.random.seed(10)
shotsX = np.random.randn(1000)*20+10
shotsY = np.random.randn(1000)*15+50

#original plot
cfg = dict(x=shotsX, y=shotsY, cmap=cmap, gridsize=22, extent=[0,100,0,100])
h   = plt.hexbin( ec="#222222",lw=2,zorder=-3,**cfg)
plt.axis('off');
1) 白光
这种方法类似于您的编辑。调用 plt.hexbin多次使用不同的线条样式以及参数 mincnt :
#draw thick white contours + overlay previous style
cfg = {**cfg,'vmin':h.get_clim()[0], 'vmax':h.get_clim()[1]}
plt.hexbin( ec="white"  ,lw=5,zorder=-2,mincnt=10,**cfg)
plt.hexbin( ec="#222222",lw=2,zorder=-1,mincnt=10,**cfg)
plt.xlim(-3,103) #required as second call of plt.hexbin()
plt.ylim(-3,103) #strangely affects the limits ...
enter image description here
严格地说,“发光”为具有许多计数的六边形增加了亮点。
2) 轮廓
仅在原始六边形顶部绘制白色轮廓线更为复杂。您可以通过以下方式解决此问题
  • 寻找六边形的顶点(即中心)
  • 为每个顶点计算线段线
  • 提取外线
  • 抽奖
  • def hexLines(a=None,i=None,off=[0,0]):
        '''regular hexagon segment lines as `(xy1,xy2)` in clockwise 
        order with points in line sorted top to bottom
        for irregular hexagon pass both `a` (vertical) and `i` (horizontal)'''
        if a is None: a = 2 / np.sqrt(3) * i;    
        if i is None: i = np.sqrt(3) / 2 * a;     
        h  = a / 2 
        xy = np.array([ [ [ 0, a], [ i, h] ], 
                        [ [ i, h], [ i,-h] ], 
                        [ [ i,-h], [ 0,-a] ], 
                        [ [-i,-h], [ 0,-a] ], #flipped
                        [ [-i, h], [-i,-h] ], #flipped
                        [ [ 0, a], [-i, h] ]  #flipped
                      ])  
        return xy+off;
    
    
    #get hexagon centers that should be highlighted
    verts = h.get_offsets()
    cnts  = h.get_array()
    highl = verts[cnts > .5*cnts.max()]
    
    #create hexagon lines
    a = ((verts[0,1]-verts[1,1])/3).round(6)
    i = ((verts[1:,0]-verts[:-1,0])/2).round(6)
    i = i[i>0][0]
    lines = np.concatenate([hexLines(a,i,off) for off in highl])
    
    #select contour lines and draw
    uls,c = np.unique(lines.round(4),axis=0,return_counts=True)
    for l in uls[c==1]: plt.plot(*l.transpose(),'w-',lw=2,scalex=False,scaley=False)
    
    enter image description here
    注意:寻找匹配的等高线取决于浮点精度np.unique(lines.round(5),...) ,这里四舍五入到小数点后 4 位。根据输入数据,这可能需要进行调整。

    关于python - Matplotlib:在 hexbin 图中使用最频繁值的 bin 组添加边框,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/65469173/

    相关文章:

    python - 在 Django 中重置密码

    python - 检查 list.remove(y) 中的 x 是否在一行中

    python - 在条形图和 Y 轴之间添加填充

    python - 我有一张星系图像,我只想绘制第 500 行

    python - 如果条件为真并且仅返回某些列,如何有条件地比较一个数据帧中的值并匹配第二个数据帧中的值?

    Windows 上的 Python Hadoop 流,脚本不是有效的 Win32 应用程序

    python - 在 Python 中计算滚动总和

    python - 通过 clf() 处理每一帧来制作 matplotlib 动画

    python - 如何从python中的mathplot识别某个y值的所有x坐标值

    python - 如何在 Matplotlib 中绘制单条等高线