Changing the linewidth and the color simultaneously in matplotlib

前端 未结 2 560
青春惊慌失措
青春惊慌失措 2020-12-31 20:23

The figure above is a great artwork showing the wind speed, wind direction and temperature simultaneously. detailedly:

  • The X axes represent the date
相关标签:
2条回答
  • 2020-12-31 21:07
    import numpy as np
    import matplotlib.pyplot as plt
    from matplotlib.collections import LineCollection
    x = np.linspace(0,4*np.pi,10000) # x data
    y = np.cos(x) # y data
    r = np.piecewise(x, [x < 2*np.pi, x >= 2*np.pi], [lambda x: 1-x/(2*np.pi), 0]) # red
    g = np.piecewise(x, [x < 2*np.pi, x >= 2*np.pi], [lambda x: x/(2*np.pi), lambda x: -x/(2*np.pi)+2]) # green
    b = np.piecewise(x, [x < 2*np.pi, x >= 2*np.pi], [0, lambda x: x/(2*np.pi)-1]) # blue
    
    a = np.ones(10000) # alpha
    w = x # width
    
    fig, ax = plt.subplots(2)
    
    ax[0].plot(x, r, color='r')
    ax[0].plot(x, g, color='g')
    ax[0].plot(x, b, color='b')
    
    # mysterious parts
    points = np.array([x, y]).T.reshape(-1, 1, 2)
    segments = np.concatenate([points[:-1], points[1:]], axis=1)
    # mysterious parts
    
    rgba = list(zip(r,g,b,a))
    
    lc = LineCollection(segments, linewidths=w, colors=rgba)
    
    ax[1].add_collection(lc)
    ax[1].set_xlim(0,4*np.pi)
    ax[1].set_ylim(-1.1,1.1)
    fig.show()
    

    I notice this is what I suffered.

    0 讨论(0)
  • 2020-12-31 21:12

    Using as inspiration another question.

    One option would be to use fill_between. But perhaps not in the way it was intended. Instead of using it to create your line, use it to mask everything that is not the line. Under it you can have a pcolormesh or contourf (for example) to map color any way you want.

    Look, for instance, at this example:

    import matplotlib.pyplot as plt
    import numpy as np
    from scipy.interpolate import interp1d
    
    def windline(x,y,deviation,color):
        y1 = y-deviation/2
        y2 = y+deviation/2
        tol = (y2.max()-y1.min())*0.05
        X, Y = np.meshgrid(np.linspace(x.min(), x.max(), 100), np.linspace(y1.min()-tol, y2.max()+tol, 100))
        Z = X.copy()
        for i in range(Z.shape[0]):
            Z[i,:] = c
    
        #plt.pcolormesh(X, Y, Z)
        plt.contourf(X, Y, Z, cmap='seismic')
    
        plt.fill_between(x, y2, y2=np.ones(x.shape)*(y2.max()+tol), color='w')
        plt.fill_between(x, np.ones(x.shape) * (y1.min() - tol), y2=y1, color='w')
        plt.xlim(x.min(), x.max())
        plt.ylim(y1.min()-tol, y2.max()+tol)
        plt.show()
    
    x = np.arange(100)
    yo = np.random.randint(20, 60, 21)
    y = interp1d(np.arange(0, 101, 5), yo, kind='cubic')(x)
    dv = np.random.randint(2, 10, 21)
    d = interp1d(np.arange(0, 101, 5), dv, kind='cubic')(x)
    co = np.random.randint(20, 60, 21)
    c = interp1d(np.arange(0, 101, 5), co, kind='cubic')(x)
    windline(x, y, d, c)
    

    , which results in this:

    The function windline accepts as arguments numpy arrays with x, y , a deviation (like a thickness value per x value), and color array for color mapping. I think it can be greatly improved by messing around with other details but the principle, although not perfect, should be solid.

    0 讨论(0)
提交回复
热议问题