matplotlib轮廓图标签重叠坐标轴

我正在制作一些轮廓图,通过clabel标记contour 。 问题是轮廓标签倾向于与轴重叠: 在这里输入图像描述

(其他一些标签很混乱,忽略)。 对于左图,10 ^ -3和10是有问题的。 在右边,10 ^ 3是唯一的问题之一。 以下是生成其中一个代码的代码:

fig = plt.figure(figsize=(6,3))
ax = fig.add_subplot(121)
ax.set_xscale('log')
ax.set_yscale('log')
ax.set_xlabel(r'$T_e$ (eV)', fontsize=10)
ax.set_ylabel(r'$n_e$ (1/cm$^3$)', fontsize=10)
ax.set_xlim(0.1, 1e4)
ax.set_ylim(1e16, 1e28)
CS = ax.contour(X, Y, Z, V, colors='k')
ax.clabel(CS, inline=True, inline_spacing=3, rightside_up=True, colors='k', fontsize=8, fmt=fmt)

有没有办法让clabel更好clabel它的位置?


考虑到文档中的例子患有同样的疾病,这表明解决这个问题不会很轻松。 看起来你必须与自动生活,使用manual放置,或弄脏你的手。

作为一种妥协,我会尝试以下两件事之一。 首先让matplotlib为你提供标签位置,然后处理那些太靠近轴的标签。

更简单的情况也是更安全的,就是摆脱靠近边界的那些clabel ,填充这些轮廓线:

# based on matplotlib.pyplot.clabel example:
import matplotlib
import numpy as np
import matplotlib.cm as cm
import matplotlib.mlab as mlab
import matplotlib.pyplot as plt

delta = 0.025
x = np.arange(-3.0, 3.0, delta)
y = np.arange(-2.0, 2.0, delta)
X, Y = np.meshgrid(x, y)
Z1 = mlab.bivariate_normal(X, Y, 1.0, 1.0, 0.0, 0.0)
Z2 = mlab.bivariate_normal(X, Y, 1.5, 0.5, 1, 1)
# difference of Gaussians
Z = 10.0 * (Z2 - Z1)


plt.figure()
CS = plt.contour(X, Y, Z)
CLS = plt.clabel(CS, inline=1, fontsize=10)

# now CLS is a list of the labels, we have to find offending ones
thresh = 0.05  # ratio in x/y range in border to discard

# get limits if they're automatic
xmin,xmax,ymin,ymax = plt.axis()
Dx = xmax-xmin
Dy = ymax-ymin

# check which labels are near a border
keep_labels = []
for label in CLS:
    lx,ly = label.get_position()
    if xmin+thresh*Dx<lx<xmax-thresh*Dx and ymin+thresh*Dy<ly<ymax-thresh*Dy:
        # inlier, redraw it later
        keep_labels.append((lx,ly))

# delete the original lines, redraw manually the labels we want to keep
# this will leave unlabelled full contour lines instead of overlapping labels

for cline in CS.collections:
    cline.remove()
for label in CLS:
    label.remove()

CS = plt.contour(X, Y, Z)
CLS = plt.clabel(CS, inline=1, fontsize=10, manual=keep_labels)

缺点是有些标签显然会丢失,当然5%的阈值应该需要针对您的特定应用进行手动调整。 以上结果与原来的相比(观看顶部):

后

我提到的另一种解决方案是采取违规标签,查看各自CS.collections数据的Path ,并尝试找到更接近图形内部的点。 由于将collections数据与标签进行配对并不简单(因为每个轮廓级别路径及其多个段对应于CS.collections的单个元素),因此可能并不值得。 特别是您可能会遇到水平线太短,以至于无法在其上放置标签,而且您还必须估计每个标签的大小。


考虑到在你的情况下,轮廓线非常简单,你也可以试着看每条轮廓线,找到最接近图形中心的点。

因此,为了演示目的,这里重建了您的数据集:

# guesstimated dummy data
X,Y = np.meshgrid(np.logspace(-3,7,200),np.logspace(13,31,200))
Z = X/Y*10**21
Vrange = range(-3,5)
V = [10**k for k in Vrange]
fmt = {lev: '$10^{%d}$'%k for (k,lev) in zip(Vrange,V)}


fig = plt.figure(figsize=(3,3))
ax = fig.add_subplot(111)
ax.set_xscale('log')
ax.set_yscale('log')
ax.set_xlabel(r'$T_e$ (eV)', fontsize=10)
ax.set_ylabel(r'$n_e$ (1/cm$^3$)', fontsize=10)
ax.set_xlim(0.1, 1e4)
ax.set_ylim(1e16, 1e28)

CS = ax.contour(X, Y, Z, V, colors='k')
ax.clabel(CS, inline=True, inline_spacing=3, rightside_up=True, colors='k', fontsize=8, fmt=fmt)

通过明确使用这两个坐标轴都是对数坐标,主要想法是将上面的最后一个坐标替换为clabel

# get limits if they're automatic
xmin,xmax,ymin,ymax = plt.axis()
# work with logarithms for loglog scale
# middle of the figure:
logmid = (np.log10(xmin)+np.log10(xmax))/2, (np.log10(ymin)+np.log10(ymax))/2

label_pos = []
for line in CS.collections:
    for path in line.get_paths():
        logvert = np.log10(path.vertices)

        # find closest point
        logdist = np.linalg.norm(logvert-logmid, ord=2, axis=1)
        min_ind = np.argmin(logdist)
        label_pos.append(10**logvert[min_ind,:])

# draw labels, hope for the best
ax.clabel(CS, inline=True, inline_spacing=3, rightside_up=True, colors='k', fontsize=8, fmt=fmt, manual=label_pos)

结果(右)与原始(左)相比较:

2之前2之后

我没有做很多努力来使轴标注漂亮,所以请忽略这些细节。 你可以看到标签确实很好地聚集在图的中间附近。 根据您的应用程序,这可能会或可能不是您想要的。

作为最后一点,标签不沿着轴的对角线放置的原因是沿着X轴和Y轴的缩放比例是不同的。 这可能会导致一些标签仍然伸出轴。 最简单的解决方案是考虑[xmin,ymax] - [xmax,ymin] (对数)线,并找出这条线与每条path的交点。 如果这是值得的,你必须在这方面投入很多:你也可以完全手动地放置你的标签。

链接地址: http://www.djcxy.com/p/22799.html

上一篇: matplotlib contour plot labels overlap axes

下一篇: How to identify array type?