Python Matplotlib重叠注释/文本
我正在尝试停止图表中的注释文本重叠。在被接受的答案中建议的方法看起来非常有希望,但是它适用于条形图。我很难将“axis”方法转换为我想做的事情,我不明白文本是如何排列的Python Matplotlib重叠注释/文本,python,matplotlib,annotate,Python,Matplotlib,Annotate,我正在尝试停止图表中的注释文本重叠。在被接受的答案中建议的方法看起来非常有希望,但是它适用于条形图。我很难将“axis”方法转换为我想做的事情,我不明白文本是如何排列的 import sys import matplotlib.pyplot as plt # start new plot plt.clf() plt.xlabel("Proportional Euclidean Distance") plt.ylabel("Percentage Timewindows Attended") p
import sys
import matplotlib.pyplot as plt
# start new plot
plt.clf()
plt.xlabel("Proportional Euclidean Distance")
plt.ylabel("Percentage Timewindows Attended")
plt.title("Test plot")
together = [(0, 1.0, 0.4), (25, 1.0127692669427917, 0.41), (50, 1.016404709797609, 0.41), (75, 1.1043426359673716, 0.42), (100, 1.1610446924342996, 0.44), (125, 1.1685687930691457, 0.43), (150, 1.3486407784550272, 0.45), (250, 1.4013999168008104, 0.45)]
together.sort()
for x,y,z in together:
plt.annotate(str(x), xy=(y, z), size=8)
eucs = [y for (x,y,z) in together]
covers = [z for (x,y,z) in together]
p1 = plt.plot(eucs,covers,color="black", alpha=0.5)
plt.savefig("test.png")
可以找到图像(如果可行)(此代码):
和(更复杂的):
我费了好大劲才弄明白。同样,最初的解决方案的功劳归于解决问题的答案 然而,我不知道如何找到文本的确切宽度和高度。如果有人知道,请发布改进(或使用该方法添加注释) 导入系统 导入matplotlib 将matplotlib.pyplot作为plt导入 将numpy作为np导入 def get_text_位置(文本、x_数据、y_数据、txt_宽度、txt_高度): a=zip(y_数据,x_数据) 文本位置=列表(y数据) 对于枚举(a)中的索引(y,x): 局部文本位置=[i为i,如果i[0]>(y-txt\u高度) 和(abs(i[1]-x)
我只是想在这里发布另一个解决方案,一个我为实现这类功能而编写的小型库: 此处可以看到该过程的一个示例: 以下是示例图像:
import matplotlib.pyplot as plt
from adjustText import adjust_text
import numpy as np
together = [(0, 1.0, 0.4), (25, 1.0127692669427917, 0.41), (50, 1.016404709797609, 0.41), (75, 1.1043426359673716, 0.42), (100, 1.1610446924342996, 0.44), (125, 1.1685687930691457, 0.43), (150, 1.3486407784550272, 0.45), (250, 1.4013999168008104, 0.45)]
together.sort()
text = [x for (x,y,z) in together]
eucs = [y for (x,y,z) in together]
covers = [z for (x,y,z) in together]
p1 = plt.plot(eucs,covers,color="black", alpha=0.5)
texts = []
for x, y, s in zip(eucs, covers, text):
texts.append(plt.text(x, y, s))
plt.xlabel("Proportional Euclidean Distance")
plt.ylabel("Percentage Timewindows Attended")
plt.title("Test plot")
adjust_text(texts, only_move={'points':'y', 'texts':'y'}, arrowprops=dict(arrowstyle="->", color='r', lw=0.5))
plt.show()
如果你想要一个完美的身材,你可以随意摆弄一下。首先,让我们也让文本排斥直线-为此,我们只需使用scipy.interpolate.interp1d沿直线创建许多虚拟点
我们希望避免沿x轴移动标签,因为出于说明目的,为什么不这样做呢。为此,我们使用参数only_move={'points':'y','text':'y'}
。如果我们只想在它们与文本重叠的情况下沿x轴移动它们,请使用move_only={'points':'y','text':'xy'}
。此外,在开始时,该函数选择文本相对于其原始点的最佳对齐方式,因此我们也只希望沿y轴进行对齐,因此autoalign='y'
。我们还减少了点的排斥力,以避免文本由于我们的人为避免线条而飞得太远。总而言之:
from scipy import interpolate
p1 = plt.plot(eucs,covers,color="black", alpha=0.5)
texts = []
for x, y, s in zip(eucs, covers, text):
texts.append(plt.text(x, y, s))
f = interpolate.interp1d(eucs, covers)
x = np.arange(min(eucs), max(eucs), 0.0005)
y = f(x)
plt.xlabel("Proportional Euclidean Distance")
plt.ylabel("Percentage Timewindows Attended")
plt.title("Test plot")
adjust_text(texts, x=x, y=y, autoalign='y',
only_move={'points':'y', 'text':'y'}, force_points=0.15,
arrowprops=dict(arrowstyle="->", color='r', lw=0.5))
plt.show()
这里的简单解决方案:(适用于jupyter笔记本电脑) 右键单击点以显示其名称 用鼠标左键单击一个加油站,将其关闭 右键单击并拖动anotation以移动它
另请参见和
get_window_extent()
是您想要旋转的美工函数。get_window_extent()返回Bbox(数组([[349.194625,38.0572],[372.132125,448.0572])。这意味着文本的宽度/高度是什么?即以显示单位表示的文本边界框。看到了吗,这个代码是从哪里来的,对吗我认为应该归功于原作者@Fraxel。在get\u text\u positions
中,a[index][2]
似乎应该被a[index][1]
取代。a
中的元素看起来确实是大小为2的元组。代码没有与提供的示例冲突,因为相关部分没有执行。干得好,Phlya!你也可以加上这个答案或类似的东西来表示感谢,我很高兴你喜欢它!还有几个其他的问题是相关的,但我还没有看到这个问题。。。我会尽量找时间写一个答案,但是如果你愿意的话,你可以自己写@Phlya:按照你在GitHub的例子,它现在可以工作了,看起来真的很棒!因为其他人可能会第一次看到您的软件包,所以我建议您更新答案和代码。@RuthgerRighart我很高兴它对您有效!谢谢你的建议,我想我会在某个时候这样做……如果有人发现错误“str”对象没有属性“values”
,请使用from scipy import interpolate
p1 = plt.plot(eucs,covers,color="black", alpha=0.5)
texts = []
for x, y, s in zip(eucs, covers, text):
texts.append(plt.text(x, y, s))
f = interpolate.interp1d(eucs, covers)
x = np.arange(min(eucs), max(eucs), 0.0005)
y = f(x)
plt.xlabel("Proportional Euclidean Distance")
plt.ylabel("Percentage Timewindows Attended")
plt.title("Test plot")
adjust_text(texts, x=x, y=y, autoalign='y',
only_move={'points':'y', 'text':'y'}, force_points=0.15,
arrowprops=dict(arrowstyle="->", color='r', lw=0.5))
plt.show()
%matplotlib notebook
import mplcursors
plt.plot.scatter(y=YOUR_Y_DATA, x =YOUR_X_DATA)
mplcursors.cursor(multiple = True).connect(
"add", lambda sel: sel.annotation.set_text(
YOUR_ANOTATION_LIST[sel.target.index]
))