在matplotlib中标记数据范围

3
我有一个 matplotlib 绘图,希望在 y 轴上用一个标签标记数据范围,并注释每个范围,类似于花括号。这里有一个类似的问题,但如果大括号应该在绘图之外的空间中而不是绘图内部,则该方法无法正常工作,在我的情况下这是必要的,因为我想要注释一个热图,而绘图内部的所有空间已经被使用。
我现在有的: enter image description here 我想要的: enter image description here 示例图的代码:
import numpy as np
import matplotlib.pyplot as plt

arr = np.array([[3,4],[2,3.5],[10,11],[9,10]])

fig = plt.figure()
ax = fig.add_subplot(111)

ax.imshow(arr)

ax.set_title("example plot")
ax.set_yticklabels([])
ax.set_yticks([])

1
也许你可以使用类似问题 https://dev59.com/lWMl5IYBdhLWcg3wc2xp 中的方法之一,通过添加一个子图到你的左侧,并关闭轴以绘制括号。你可以使用 gridspec 来使左侧子图比右侧子图更窄。 - j_4321
2个回答

1
我无法做出评论中的高级操作,但我尝试使用“Latex”做了我能做的事情。这不是你的答案,但我会分享给你作为参考。
import numpy as np
import matplotlib.pyplot as plt

arr = np.array([[3,4],[2,3.5],[10,11],[9,10]])

fig = plt.figure(figsize=(4,4))
ax = fig.add_subplot(111)

ax.imshow(arr)

ax.set_title("example plot")
ax.text(-1.10, 0.25, r'$group 1$', fontsize=24, ha='left', va='center', rotation='horizontal', transform=ax.transAxes)
ax.text(-0.35, 0.25, '$\{$', fontsize=72, ha='left', va='center', rotation='horizontal', transform=ax.transAxes)
ax.text(-1.10, 0.75, r'$group 2$', fontsize=24, ha='left', va='center', rotation='horizontal', transform=ax.transAxes)
ax.text(-0.35, 0.75, '$\{$', fontsize=72, ha='left', va='center', rotation='horizontal', transform=ax.transAxes)
ax.set_yticklabels([])
ax.set_yticks([])

enter image description here


谢谢,我认为这是一个好的、简单的解决方法,如果组的大小相等的话,但这并不一定适用于我想标记的数据。 - Balthasar

0
感谢j_4321的建议和链接问题中的响应代码,我想出了以下解决方案。它并不完美,因为我仍然需要手动调整不同大小图形的值。它还需要自动方面,这会使热力图有些倾斜:
import numpy as np
import matplotlib.pyplot as plt
import matplotlib.gridspec as gridspec

def draw_brace(ax, span, text, axis):
    """Draws an annotated brace on the axes."""
    # axis could be reversed
    xx = ax.get_xlim()
    xmin = np.min(xx)
    xmax = np.max(xx)
    yy = ax.get_ylim()
    ymin = np.min(yy)
    ymax = np.max(yy)
    xspan = xmax - xmin
    yspan = ymax - ymin
    
    if axis=="y":
        tspan = yspan
        ospan = xspan
        omin  = xmin
    else:
        ospan = yspan
        omin  = ymin
        tspan = xspan
    
    amin, amax = span
    span = amax - amin
    
    resolution = int(span/tspan*100)*2+1 # guaranteed uneven
    beta = 300./tspan # the higher this is, the smaller the radius
    
    x = np.linspace(amin, amax, resolution)
    x_half = x[:resolution//2+1]
    y_half_brace = (1/(1.+np.exp(-beta*(x_half-x_half[0])))
                    + 1/(1.+np.exp(-beta*(x_half-x_half[-1]))))
    y = np.concatenate((y_half_brace, y_half_brace[-2::-1]))
    y = omin + (.05*y - .01)*ospan # adjust vertical position

    #ax.autoscale(False)
    if axis == "y":
        ax.plot(-y +1 , x, color='black', lw=1)
        ax.text(0.8+ymin+.07*yspan, (amax+amin)/2., text, ha='center', va='center')
    else:
        ax.plot(x, y, color='black', lw=1)
        ax.text((amax+amin)/2.,ymin+.07*yspan, text, ha='center', va='center')
    

arr = np.array([[3,4],[2,3.5],[10,11],[9,10]])
fig = plt.figure()

gs = fig.add_gridspec(nrows=1, ncols=2, wspace=0,width_ratios=[1,4])

ax2 = fig.add_subplot(gs[:, 1])

ax2.imshow(arr)
ax2.set_title("example plot")

ax2.set_yticklabels([])
ax2.set_yticks([])
ax2.set_xticklabels([])
ax2.set_aspect('auto')

ax1 = fig.add_subplot(gs[:, 0], sharey=ax2)
ax1.set_xticks([])
ax1.set_xticklabels([])
ax1.set_aspect('auto')
ax1.set_xlim([0,1])
ax1.axis('off')
draw_brace(ax1, (0, 1), 'group1',"y")
draw_brace(ax1, (2, 3), 'group2',"y")

fig.subplots_adjust(wspace=0, hspace=0)

这将创建以下图表: 输入图片描述


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接