Waterfall plot python?

后端 未结 4 1284
独厮守ぢ
独厮守ぢ 2020-12-05 05:23

Is there a python module that will do a waterfall plot like MATLAB does? I googled \'numpy waterfall\', \'scipy waterfall\', and \'matplotlib waterfall\', but did not find a

相关标签:
4条回答
  • 2020-12-05 05:39

    The Wikipedia type of Waterfall chart one can obtain also like this:

    import numpy as np
    import pandas as pd
    
    def waterfall(series):
        df = pd.DataFrame({'pos':np.maximum(series,0),'neg':np.minimum(series,0)})
        blank = series.cumsum().shift(1).fillna(0)
        df.plot(kind='bar', stacked=True, bottom=blank, color=['r','b'])
        step = blank.reset_index(drop=True).repeat(3).shift(-1)
        step[1::3] = np.nan
        plt.plot(step.index, step.values,'k')
    
    test = pd.Series(-1 + 2 * np.random.rand(10), index=list('abcdefghij'))
    waterfall(test)
    
    0 讨论(0)
  • 2020-12-05 05:47

    You can do a waterfall in matplotlib using the PolyCollection class. See this specific example to have more details on how to do a waterfall using this class.

    Also, you might find this blog post useful, since the author shows that you might obtain some 'visual bug' in some specific situation (depending on the view angle chosen).

    Below is an example of a waterfall made with matplotlib (image from the blog post):
    (source: austringer.net)

    0 讨论(0)
  • 2020-12-05 05:49

    I have generated a function that replicates the matlab waterfall behaviour in matplotlib. That is:

    1. It generates the 3D shape as many independent and parallel 2D curves
    2. Its color comes from a colormap in the z values

    I started from two examples in matplotlib documentation: multicolor lines and multiple lines in 3d plot. From these examples, I only saw possible to draw lines whose color varies following a given colormap according to its z value following the example, which is reshaping the input array to draw the line by segments of 2 points and setting the color of the segment to the z mean value between these 2 points.

    Thus, given the input matrixes n,m matrixes X,Y and Z, the function loops over the smallest dimension between n,m to plot each of the waterfall plot independent lines as a line collection of the 2 points segments as explained above.

    def waterfall_plot(fig,ax,X,Y,Z,**kwargs):
        '''
        Make a waterfall plot
        Input:
            fig,ax : matplotlib figure and axes to populate
            Z : n,m numpy array. Must be a 2d array even if only one line should be plotted
            X,Y : n,m array
            kwargs : kwargs are directly passed to the LineCollection object
        '''
        # Set normalization to the same values for all plots
        norm = plt.Normalize(Z.min().min(), Z.max().max())
        # Check sizes to loop always over the smallest dimension
        n,m = Z.shape
        if n>m:
            X=X.T; Y=Y.T; Z=Z.T
            m,n = n,m
    
        for j in range(n):
            # reshape the X,Z into pairs 
            points = np.array([X[j,:], Z[j,:]]).T.reshape(-1, 1, 2)
            segments = np.concatenate([points[:-1], points[1:]], axis=1)  
            # The values used by the colormap are the input to the array parameter
            lc = LineCollection(segments, cmap='plasma', norm=norm, array=(Z[j,1:]+Z[j,:-1])/2, **kwargs)
            line = ax.add_collection3d(lc,zs=(Y[j,1:]+Y[j,:-1])/2, zdir='y') # add line to axes
    
        fig.colorbar(lc) # add colorbar, as the normalization is the same for all
        # it doesent matter which of the lc objects we use
        ax.auto_scale_xyz(X,Y,Z) # set axis limits
    

    Therefore, plots looking like matlab waterfall can be easily generated with the same input matrixes as a matplotlib surface plot:

    import numpy as np; import matplotlib.pyplot as plt
    from matplotlib.collections import LineCollection
    from mpl_toolkits.mplot3d import Axes3D
    
    # Generate data
    x = np.linspace(-2,2, 500)
    y = np.linspace(-2,2, 60)
    X,Y = np.meshgrid(x,y)
    Z = np.sin(X**2+Y**2)-.2*X
    # Generate waterfall plot
    fig = plt.figure()
    ax = fig.add_subplot(111, projection='3d')
    waterfall_plot(fig,ax,X,Y,Z,linewidth=1.5,alpha=0.5) 
    ax.set_xlabel('X'); ax.set_ylabel('Y'); ax.set_zlabel('Z') 
    fig.tight_layout()
    

    The function assumes that when generating the meshgrid, the x array is the longest, and by default the lines have fixed y, and its the x coordinate what varies. However, if the size of the y array is longer, the matrixes are transposed, generating the lines with fixed x. Thus, generating the meshgrid with the sizes inverted (len(x)=60 and len(y)=500) yields:

    To see what are the possibilities of the **kwargs argument, refer to the LineCollection class documantation and to its set_ methods.

    0 讨论(0)
  • 2020-12-05 05:59

    Have a look at mplot3d:

    # copied from 
    # http://matplotlib.sourceforge.net/mpl_examples/mplot3d/wire3d_demo.py
    
    from mpl_toolkits.mplot3d import axes3d
    import matplotlib.pyplot as plt
    import numpy as np
    
    fig = plt.figure()
    ax = fig.add_subplot(111, projection='3d')
    X, Y, Z = axes3d.get_test_data(0.05)
    ax.plot_wireframe(X, Y, Z, rstride=10, cstride=10)
    
    plt.show()
    

    http://matplotlib.sourceforge.net/mpl_toolkits/mplot3d/tutorial.html#wireframe-plots

    I don't know how to get results as nice as Matlab does.


    If you want more, you may also have a look at MayaVi: http://mayavi.sourceforge.net/

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