代码之家  ›  专栏  ›  技术社区  ›  ImportanceOfBeingErnest

如何绘制温度计图?

  •  0
  • ImportanceOfBeingErnest  · 技术社区  · 7 年前

    question

    如何在matplotlib中绘制温度计?

    marker 或者 Path . 不过,温度计似乎没有任何unicode符号。 Font awesome 在matplotlib中有温度计符号和绘图符号 is possible . 但是只有5种不同的填充物

    enter image description here

    那么,有没有可能有一个温度符号,其中水银柱编码的温度(或事实上任何其他数量)在颜色和填充水平方面?如果是,怎么做?

    ( 我在下面给出了一个答案,这个方法的替代品或改进在这里作为进一步的答案是受欢迎的。 )

    1 回复  |  直到 7 年前
        1
  •  13
  •   ImportanceOfBeingErnest    7 年前

    绘制由两部分组成的温度计的一个选项是创建两个 Path s、 外壳和内部水银柱。为此,可以从头开始创建路径,并允许内部路径根据(规范化的)输入参数而变化。

    scatter scatter ,只不过它还需要附加参数 temp tempnorm 作为输入的温度标准化。

    import numpy as np
    import matplotlib.pyplot as plt
    import matplotlib.path as mpath
    
    class TemperaturePlot():
    
        @staticmethod
        def get_hull():
            verts1 = np.array([[0,-128],[70,-128],[128,-70],[128,0],
                              [128,32.5],[115.8,61.5],[96,84.6],[96,288],
                              [96,341],[53,384],[0,384]])
            verts2 = verts1[:-1,:] * np.array([-1,1])
            codes1 = [1,4,4,4,4,4,4,2,4,4,4]
            verts3 = np.array([[0,-80],[44,-80],[80,-44],[80,0],
                              [80,34.3],[60.7,52],[48,66.5],[48,288],
                              [48,314],[26.5,336],[0,336]])
            verts4 = verts3[:-1,:] * np.array([-1,1])
            verts = np.concatenate((verts1, verts2[::-1], verts4, verts3[::-1]))
            codes = codes1 + codes1[::-1][:-1]
            return mpath.Path(verts/256., codes+codes)
    
        @staticmethod
        def get_mercury(s=1):
            a = 0; b = 64; c = 35
            d = 320 - b
            e = (1-s)*d
            verts1 = np.array([[a,-b],[c,-b],[b,-c],[b,a],[b,c],[c,b],[a,b]])
            verts2 = verts1[:-1,:] * np.array([-1,1])
            verts3 = np.array([[0,0],[32,0],[32,288-e],[32,305-e],
                               [17.5,320-e],[0,320-e]])
            verts4 = verts3[:-1,:] * np.array([-1,1])
            codes = [1] + [4]*12 + [1,2,2,4,4,4,4,4,4,2,2]
            verts = np.concatenate((verts1, verts2[::-1], verts3, verts4[::-1]))
            return mpath.Path(verts/256., codes)
    
        def scatter(self, x,y, temp=1, tempnorm=None, ax=None, **kwargs):
            self.ax = ax or plt.gca()
            temp = np.atleast_1d(temp)
            ec = kwargs.pop("edgecolor", "black")
            kwargs.update(linewidth=0)
            self.inner = self.ax.scatter(x,y, **kwargs)
            kwargs.update(c=None, facecolor=ec, edgecolor=None, color=None)
            self.outer = self.ax.scatter(x,y, **kwargs)
            self.outer.set_paths([self.get_hull()])
            if not tempnorm:
                mi, ma = np.nanmin(temp), np.nanmax(temp)
                if mi == ma:
                    mi=0
                tempnorm = plt.Normalize(mi,ma)
            ipaths = [self.get_mercury(tempnorm(t)) for t in temp]
            self.inner.set_paths(ipaths)
    

    这个类的用法可能是这样的,

    plt.rcParams["figure.figsize"] = (5.5,3) 
    plt.rcParams["figure.dpi"] = 72*3
    
    fig, ax = plt.subplots()
    p = TemperaturePlot()
    p.scatter([.25,.5,.75], [.3,.4,.5], s=[800,1200,1600], temp=[28,39,35], color="C3",
              ax=ax, transform=ax.transAxes)
    
    plt.show()
    

    [28,39,35] 在最小值和最大值之间。

    enter image description here

    或者我们可以用颜色( c ) 临时雇员 显示温度

    np.random.seed(42)
    fig, ax = plt.subplots()
    n = 42
    x = np.linspace(0,100,n)
    y = np.cumsum(np.random.randn(n))+5
    
    ax.plot(x,y, color="darkgrey", lw=2.5)
    
    p = TemperaturePlot()
    p.scatter(x[::4],y[::4]+3, s=300, temp=y[::4], c=y[::4], edgecolor="k", cmap="RdYlBu_r")
    
    ax.set_ylim(-6,18)
    plt.show()
    

    enter image description here