【问题标题】:How to draw multiple triangles with different sizes and directions based on data using plotting tools like Matplotlib如何使用 Matplotlib 等绘图工具根据数据绘制不同大小和方向的多个三角形
【发布时间】:2023-04-05 16:40:01
【问题描述】:

我想绘制如下图所示的图形。它的 x 轴是数据点的顺序,例如从 1 到 7。y 轴是从 0 到 25 的刻度。例如,如果我想用它的数据 (1,22,20) 绘制一个三角形,那么 '1' 给出了所有数据点之间的顺序(不同的三角形),三角形应该画在最左边; “22,20”给出三角形沿 y 轴的“底端”。

有谁知道如何使用 matplotlib python 包在图中绘制具有多个数字的三角形?

【问题讨论】:

    标签: python matplotlib data-visualization


    【解决方案1】:

    阅读 this postthis post 了解使用 matplotlib 绘制多边形。

    EDIT1: 刚刚看到@Poolka 的回答。这也是我要走的路,但请注意,在上述链接之一中,指出向图中添加单个多边形 (p = pat.Polygon([[x1, y1], [x2, y2], [x3, y3]); ax.add_patch(p)) 可能会变得非常慢,因此首选集合。

    编辑 2: 另请参阅 TheImportanceOfBeingErnest 的回答,了解此概念的更详细版本。 连同这段 sn-p 代码,它应该可以帮助您:

    import numpy as np
    import matplotlib
    import matplotlib.pyplot as plt
    import matplotlib.patches as pat  # Patches like pat.Polygon()
    from matplotlib.collections import PolyCollection  # Collections of patches
    
    test = ((1, 22, 20),
            (2, 21, 19.5),
            (3, 18, 20))  # Test data
    
    triangles = []
    fig, ax = plt.subplots(1, 1)
    
    for t in test:
        xmid = t[0]  # Middle x-coord
        xleft = t[0] - 0.5
        xright = t[0] + 0.5  # Use fixed width of 0.5
    
        y1 = t[1]  # y-coords
        y2 = t[2]
    
        coordinates = [[xleft, y1], [xright, y1], [xmid, y2]]
    
        print(coordinates) 
        triangles.append(coordinates)  # Append to collection
    
    z = np.random.random(len(triangles))
    collec = PolyCollection(triangles, array=z, cmap=matplotlib.cm.viridis)
    
    ax.add_collection(collec)  # Plot polygon collection
    ax.autoscale_view()
    plt.show()
    

    【讨论】:

    • 应该永远是coordinates = [[xleft, y1], [xright, y1], [xmid, y2]],与顺序无关!!
    • 我现在删除了那条多余的行。请注意,您的两个链接具有相同的目标。仍然赞成。
    • 天哪,我想我有点分心了,哈哈。我会更新第二个链接。
    【解决方案2】:

    考虑以下简单示例:

    import matplotlib.pyplot as plt
    
    # data
    data = [[1, 22, 20], [3, 20, 25]]
    
    plt.figure()
    for val in data:
        # coordinates
        dy = val[1] - val[2]
        dx = abs(dy) / 2
        x0 = val[0]
        y0 = val[1]
        # drawing
        triangle = plt.Polygon([[x0, y0], [x0 - dx, y0 + dy], [x0 + dx, y0 + dy]])
        plt.gca().add_patch(triangle)
    
    # misc
    plt.grid()
    plt.axis('square')
    # these 2 lines are needed because patches in matplotlib do not adjust axes limits automatically, another approach is to add some data to the figure with plot, scatter, etc.
    plt.xlim([-20, 20])
    plt.ylim([0, 40])
    

    结果是:

    【讨论】:

      【解决方案3】:

      在这种情况下,使用PolyCollection(如@cripcate's answer 所示)是有利的。使用单个 numpy 数组的更精简的版本可能如下所示:

      import numpy as np
      import matplotlib.pyplot as plt
      from matplotlib.collections import PolyCollection
      
      def triangle_collection(d, ax=None, width=0.4, **kwargs):
          ax = ax or plt.gca()
          verts = np.c_[d[:,0]-width/2, d[:,1], d[:,0]+width/2, 
                        d[:,1], d[:,0], d[:,2]].reshape(len(d),3,2)
          c = PolyCollection(verts, **kwargs)
          ax.add_collection(c)
          ax.autoscale()
          return c
      
      
      data = np.array([(1,22,20), (2,21,19.5), (3,18,20),
                       (4,17,19), (5,15,17), (6,11,8.5), (7,14,12)])
      
      fig, ax = plt.subplots()
      fig.subplots_adjust(left=0.3, right=0.7)
      
      triangle_collection(data, facecolors=plt.cm.tab10(np.arange(len(data))))
      
      plt.show() 
      

      【讨论】:

        猜你喜欢
        • 2014-06-21
        • 1970-01-01
        • 1970-01-01
        • 2019-05-24
        • 2017-10-27
        • 1970-01-01
        • 2013-11-26
        • 2021-03-11
        • 1970-01-01
        相关资源
        最近更新 更多