How to plot multiple regression 3D plot in python

10,858

for matplotlib, you can base off the surface example (you're missing plt.meshgrid):

from mpl_toolkits.mplot3d import Axes3D
from matplotlib import cm
from matplotlib.ticker import LinearLocator, FormatStrFormatter
import matplotlib.pyplot as plt
import numpy as np

fig = plt.figure()
ax = fig.gca(projection='3d')
X = np.arange(-5, 5, 0.25)
Y = np.arange(-5, 5, 0.25)
X, Y = np.meshgrid(X, Y)
R = np.sqrt(X**2 + Y**2)
Z = np.sin(R)
surf = ax.plot_surface(X, Y, Z, rstride=1, cstride=1, cmap=cm.coolwarm,
                       linewidth=0, antialiased=False)
ax.set_zlim(-1.01, 1.01)

ax.zaxis.set_major_locator(LinearLocator(10))
ax.zaxis.set_major_formatter(FormatStrFormatter('%.02f'))

fig.colorbar(surf, shrink=0.5, aspect=5)

plt.show()
Share:
10,858
user2738815
Author by

user2738815

Updated on June 04, 2022

Comments

  • user2738815
    user2738815 almost 2 years

    I am not a scientist, so please assume that I do not know the jargon of experienced programmers, or the intricacies of scientific plotting techniques. Python is the only language I know (beginner+, maybe intermediate).

    Task : Plot the results of a multiple regression (z = f(x, y) ) as a two dimensional plane on a 3D graph (as I can using OSX’s graphing utility, for example, or as implemented here Plot Regression Surface with R).

    After a week searching Stackoverflow and reading various documentations of matplotlib, seaborn and mayavi I finally found Simplest way to plot 3d surface given 3d points which sounded promising. So here is my data and code:

    First try with matplotlib:

    shape: (80, 3) 
    type: <type 'numpy.ndarray'> 
    zmul: 
    
    [[  0.00000000e+00   0.00000000e+00   5.52720000e+00]
     [  5.00000000e+02   5.00000000e-01   5.59220000e+00]
     [  1.00000000e+03   1.00000000e+00   5.65720000e+00]
     [  1.50000000e+03   1.50000000e+00   5.72220000e+00]
     [  2.00000000e+03   2.00000000e+00   5.78720000e+00]
     [  2.50000000e+03   2.50000000e+00   5.85220000e+00]
     ……]
    
    import matplotlib
    from matplotlib.ticker import MaxNLocator
    from matplotlib import cm
    
    from numpy.random import randn
    from scipy import array, newaxis
    Xs = zmul[:,0]
    Ys = zmul[:,1]
    Zs = zmul[:,2]
    
    
    surf = ax.plot_trisurf(Xs, Ys, Zs, cmap=cm.jet, linewidth=0)
    fig.colorbar(surf)
    
    ax.xaxis.set_major_locator(MaxNLocator(5))
    ax.yaxis.set_major_locator(MaxNLocator(6))
    ax.zaxis.set_major_locator(MaxNLocator(5))
    
    fig.tight_layout()
    
    plt.show()
    

    All I get is an empty 3D coordinate frame with the following error message:

    RuntimeError: Error in qhull Delaunay triangulation calculation: singular input data (exitcode=2); use python verbose option (-v) to see original qhull error.

    I tried to see if I could play around with the plotting parameters and checked this site http://www.qhull.org/html/qh-impre.htm#delaunay, but I really cannot make sense of what I am supposed to do.

    Second try with mayavi:

    Same data, divided into 3 numpy arrays:

    type: <type 'numpy.ndarray'> 
    X: [    0   500  1000  1500  2000  2500  3000 ….]
    
    type: <type 'numpy.ndarray'> 
    Y: [  0.    0.5   1.    1.5   2.    2.5   3.  ….]
    
    type: <type 'numpy.ndarray'> 
    Z: [  5.5272   5.5922   5.6572   5.7222   5.7872   5.8522   5.9172  ….] 
    

    Code:

    from mayavi import mlab
    def multiple3_triple(tpl_lst):
    
    X = xs
    Y = ys
    Z = zs
    
    
    # Define the points in 3D space
    # including color code based on Z coordinate.
    pts = mlab.points3d(X, Y, Z, Z)
    
    # Triangulate based on X, Y with Delaunay 2D algorithm.
    # Save resulting triangulation.
    mesh = mlab.pipeline.delaunay2d(pts)
    
    # Remove the point representation from the plot
    pts.remove()
    
    # Draw a surface based on the triangulation
    surf = mlab.pipeline.surface(mesh)
    
    # Simple plot.
    mlab.xlabel("x")
    mlab.ylabel("y")
    mlab.zlabel("z")
    mlab.show()
    

    All I get is this:

    enter image description here

    If this matters, I am using the 64 bit version of Enthought's Canopy on OSX 10.9.3

    Will be grateful for any input on what I am doing wrong.

    EDIT: Posting the final code that worked, in case it helps someone.

    '''After the usual imports'''
    def multiple3(tpl_lst):
        mul = []
        for tpl in tpl_lst:
            calc = (.0001*tpl[0]) + (.017*tpl[1])+ 6.166
            mul.append(calc)
        return mul
    
    fig = plt.figure()
    ax = fig.gca(projection='3d')
    '''some skipped code for the scatterplot'''
    X = np.arange(0, 40000, 500)
    Y = np.arange(0, 40, .5)
    X, Y = np.meshgrid(X, Y)
    Z = multiple3(zip(X,Y))
    
    surf = ax.plot_surface(X, Y, Z, rstride=1, cstride=1,cmap=cm.autumn,
                           linewidth=0, antialiased=False, alpha =.1)
    ax.set_zlim(1.01, 11.01)
    ax.set_xlabel(' x = IPP')
    ax.set_ylabel('y = UNRP20')
    ax.set_zlabel('z = DI')
    
    ax.zaxis.set_major_locator(LinearLocator(10))
    ax.zaxis.set_major_formatter(FormatStrFormatter('%.02f'))
    fig.colorbar(surf, shrink=0.5, aspect=5)
    plt.show()
    

    enter image description here