【问题标题】:Matplotlib scatter plot with different text at each data pointMatplotlib 散点图在每个数据点具有不同的文本
【发布时间】:2013-01-04 03:34:09
【问题描述】:

我正在尝试制作散点图并用列表中的不同数字注释数据点。 因此,例如,我想绘制 yx 并使用来自 n 的相应数字进行注释。

y = [2.56422, 3.77284, 3.52623, 3.51468, 3.02199]
z = [0.15, 0.3, 0.45, 0.6, 0.75]
n = [58, 651, 393, 203, 123]
ax = fig.add_subplot(111)
ax1.scatter(z, y, fmt='o')

有什么想法吗?

【问题讨论】:

标签: python matplotlib text scatter-plot annotate


【解决方案1】:

我不知道任何采用数组或列表的绘图方法,但您可以在迭代 n 中的值时使用 annotate()

y = [2.56422, 3.77284, 3.52623, 3.51468, 3.02199]
z = [0.15, 0.3, 0.45, 0.6, 0.75]
n = [58, 651, 393, 203, 123]

fig, ax = plt.subplots()
ax.scatter(z, y)

for i, txt in enumerate(n):
    ax.annotate(txt, (z[i], y[i]))

annotate() 有很多格式选项,请参阅matplotlib website:

【讨论】:

  • 在 Seaborn regplots 上运行良好,也没有太多干扰。
  • @Rutger 我使用 pandas 数据帧,但不知何故得到了一个 KeyError- 所以我猜应该是一个 dict() 对象?有没有其他方法可以使用enumerateannotate 和 pandas 数据框来标记数据?
  • @Rachel,您可以使用for row in df.iterrows():,然后使用row['text'], row['x-coord'] 等访问值。如果您发布一个单独的问题,我会看看它。
  • 对于碰巧非常接近的点,有没有办法偏移注释并绘制从数据点指向标签的线,以便很好地分离其他重叠的标签?
  • @aviator,不幸的是不是内置的。但是例如使用networkx的布局引擎看这个:stackoverflow.com/a/34697108/1755432
【解决方案2】:

在 matplotlib 2.0 之前的版本中,ax.scatter 不需要绘制没有标记的文本。在 2.0 版中,您需要 ax.scatter 为文本设置正确的范围和标记。

y = [2.56422, 3.77284, 3.52623, 3.51468, 3.02199]
z = [0.15, 0.3, 0.45, 0.6, 0.75]
n = [58, 651, 393, 203, 123]

fig, ax = plt.subplots()

for i, txt in enumerate(n):
    ax.annotate(txt, (z[i], y[i]))

link 中,您可以找到一个 3d 示例。

【讨论】:

  • 这太棒了!感谢您分享此解决方案。您还可以分享设置图形大小的正确代码吗?诸如plt.figure(figsize=(20,10)) 之类的实现没有按预期工作,因为调用此代码实际上并没有改变图像的大小。期待您的协助。谢谢!
  • fig, ax = plt.subplots(figsize=(20,10))
【解决方案3】:

当您需要在不同时间单独注释时,这可能很有用(我的意思是,不是在单个 for 循环中)

ax = plt.gca()
ax.annotate('your_lable', (x,y)) 

其中xy 是您的目标坐标,类型为float/int。

【讨论】:

    【解决方案4】:

    您也可以使用pyplot.text(参见here)。

    def plot_embeddings(M_reduced, word2Ind, words):
        """ 
            Plot in a scatterplot the embeddings of the words specified in the list "words".
            Include a label next to each point.
        """
        for word in words:
            x, y = M_reduced[word2Ind[word]]
            plt.scatter(x, y, marker='x', color='red')
            plt.text(x+.03, y+.03, word, fontsize=9)
        plt.show()
    
    M_reduced_plot_test = np.array([[1, 1], [-1, -1], [1, -1], [-1, 1], [0, 0]])
    word2Ind_plot_test = {'test1': 0, 'test2': 1, 'test3': 2, 'test4': 3, 'test5': 4}
    words = ['test1', 'test2', 'test3', 'test4', 'test5']
    plot_embeddings(M_reduced_plot_test, word2Ind_plot_test, words)
    

    【讨论】:

      【解决方案5】:

      对于有限的一组值,matplotlib 很好。但是,当您有很多值时,工具提示开始与其他数据点重叠。但是由于空间有限,您不能忽略这些值。因此最好缩小或放大。

      使用情节

      import plotly.express as px
      df = px.data.tips()
      
      df = px.data.gapminder().query("year==2007 and continent=='Americas'")
      
      
      fig = px.scatter(df, x="gdpPercap", y="lifeExp", text="country", log_x=True, size_max=100, color="lifeExp")
      fig.update_traces(textposition='top center')
      fig.update_layout(title_text='Life Expectency', title_x=0.5)
      fig.show()
      

      【讨论】:

      • 您在这里使用什么进行内联缩放?不是mpld3,是吗?
      • 恕我直言,这种速度的动画并没有增加任何东西,精心设计的固定图像会不那么令人沮丧。
      【解决方案6】:

      我想补充一点,您甚至可以使用箭头/文本框来注释标签。这就是我的意思:

      import random
      import matplotlib.pyplot as plt
      
      
      y = [2.56422, 3.77284, 3.52623, 3.51468, 3.02199]
      z = [0.15, 0.3, 0.45, 0.6, 0.75]
      n = [58, 651, 393, 203, 123]
      
      fig, ax = plt.subplots()
      ax.scatter(z, y)
      
      ax.annotate(n[0], (z[0], y[0]), xytext=(z[0]+0.05, y[0]+0.3), 
          arrowprops=dict(facecolor='red', shrink=0.05))
      
      ax.annotate(n[1], (z[1], y[1]), xytext=(z[1]-0.05, y[1]-0.3), 
          arrowprops = dict(  arrowstyle="->",
                              connectionstyle="angle3,angleA=0,angleB=-90"))
      
      ax.annotate(n[2], (z[2], y[2]), xytext=(z[2]-0.05, y[2]-0.3), 
          arrowprops = dict(arrowstyle="wedge,tail_width=0.5", alpha=0.1))
      
      ax.annotate(n[3], (z[3], y[3]), xytext=(z[3]+0.05, y[3]-0.2), 
          arrowprops = dict(arrowstyle="fancy"))
      
      ax.annotate(n[4], (z[4], y[4]), xytext=(z[4]-0.1, y[4]-0.2),
          bbox=dict(boxstyle="round", alpha=0.1), 
          arrowprops = dict(arrowstyle="simple"))
      
      plt.show()
      

      这将生成以下图表:

      【讨论】:

        【解决方案7】:

        Python 3.6+:

        coordinates = [('a',1,2), ('b',3,4), ('c',5,6)]
        for x in coordinates: plt.annotate(x[0], (x[1], x[2]))
        

        【讨论】:

        • 到那时,为什么不做coordinates = [('a',(1,2)), ('b',(3,4)), ('c',(5,6))]plt.annotate(*x)
        【解决方案8】:

        作为一个使用列表理解和numpy的单行:

        [ax.annotate(x[0], (x[1], x[2])) for x in np.array([n,z,y]).T]

        设置与 Rutger 的回答相同。

        【讨论】:

        • 使用deque(..., maxlen=0)之类的东西,而不是创建不需要值列表的列表推导式。
        • 或像普通人一样使用常规的 for 循环。列表推导是惊人的和强大的,但它不应该在这种情况下使用
        【解决方案9】:

        如果有人试图将上述解决方案应用于 .scatter() 而不是 .subplot(),

        我尝试运行以下代码

        y = [2.56422, 3.77284, 3.52623, 3.51468, 3.02199]
        z = [0.15, 0.3, 0.45, 0.6, 0.75]
        n = [58, 651, 393, 203, 123]
        
        fig, ax = plt.scatter(z, y)
        
        for i, txt in enumerate(n):
            ax.annotate(txt, (z[i], y[i]))
        

        但遇到了“无法解压缩不可迭代的 PathCollection 对象”的错误,该错误专门指向代码行 fig, ax = plt.scatter(z, y)

        我最终使用以下代码解决了错误

        plt.scatter(z, y)
        
        for i, txt in enumerate(n):
            plt.annotate(txt, (z[i], y[i]))
        

        我没想到 .scatter() 和 .subplot() 之间会有区别 我应该知道的更好。

        【讨论】:

        • 我在我的一个脚本(这里的第二个块)中使用了完全相同的代码,但我遇到了一条错误消息,说“IndexError:索引 1 超出了轴 0 的范围大小为 1”,指的是 annotate 函数中的“txt”。知道为什么会这样吗?
        猜你喜欢
        • 2020-12-19
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2021-12-11
        • 2014-12-16
        • 2011-05-15
        相关资源
        最近更新 更多