matplotlib:如何在散点图上自动放置箭头注释点?

27 python numpy matplotlib scipy

如果我用matplotlib制作一个散点图:

plt.scatter(randn(100),randn(100))
# set x, y lims
plt.xlim([...])
plt.ylim([...])
Run Code Online (Sandbox Code Playgroud)

我想(x, y)用箭头指向它和标签来注释给定点.我知道这可以完成annotate,但我希望箭头及其标签以"最佳"方式放置,如果可能(给定当前轴比例/限制)箭头和标签不重叠与其他点.例如,如果你想标记异常点.有没有办法做到这一点?它不一定是完美的,而只是箭头/标签的智能放置,只给出(x,y)要标记的点的坐标.谢谢.

Joe*_*ton 35

基本上,不,没有.

处理与此类似的地图标签处理的布局引擎非常复杂,超出了matplotlib的范围.(边界框交叉点实际上是决定标签放置位置的一种相当差的方式.编写大量代码的重点是什么,只能在一个案例中用于1000个?)

除此之外,由于matplotlib所做的复杂文本渲染量(例如乳胶),如果不先完全渲染文本(这相当慢),就无法确定文本的范围.

但是,在许多情况下,您会发现使用带有注释的标签后面的透明框是一种合适的解决方法.

例如

import numpy as np
import matplotlib.pyplot as plt

np.random.seed(1)
x, y = np.random.random((2,500))

fig, ax = plt.subplots()
ax.plot(x, y, 'bo')

# The key option here is `bbox`. I'm just going a bit crazy with it.
ax.annotate('Something', xy=(x[0], y[0]), xytext=(-20,20), 
            textcoords='offset points', ha='center', va='bottom',
            bbox=dict(boxstyle='round,pad=0.2', fc='yellow', alpha=0.3),
            arrowprops=dict(arrowstyle='->', connectionstyle='arc3,rad=0.5', 
                            color='red'))

plt.show()
Run Code Online (Sandbox Code Playgroud)

在此输入图像描述

  • 我喜欢你的榜样.也可以将注释放在框架外,例如使用"轴分数"作为"textcoords".放置的自动性质可以包装成一个创建注释的小方法.如果该点最接近底部中心,则将其放在x轴下方; 如果它更接近右边缘,把它放在那里,甚至可以自动旋转它....仍然需要一点点技巧,因为它可能会隐藏刻度标签,或者被图形的边缘裁剪等等... (2认同)

Phl*_*lya 5

使用adjustText(完全披露,是我写的)。

让我们标记前10点。我更改的唯一参数是降低点的排斥力,因为它们的数量太多,我们希望该算法花费更多时间并更仔细地放置注释。

import numpy as np
import matplotlib.pyplot as plt
from adjustText import adjust_text
np.random.seed(1)
x, y = np.random.random((2,500))

fig, ax = plt.subplots()
ax.plot(x, y, 'bo')
ts = []
for i in range(10):
    ts.append(plt.text(x[i], y[i], 'Something'+str(i)))
adjust_text(ts, x=x, y=y, force_points=0.1, arrowprops=dict(arrowstyle='->', 
color='red'))
plt.show()
Run Code Online (Sandbox Code Playgroud)

在此处输入图片说明 这不是理想的,但是此处的点确实很密集,有时无法将文本放置在靠近目标的位置而不会重叠它们。但这都是自动且易于使用的,并且也不会让标签相互重叠。

PS它使用边界框相交,但我会说成功了!