Principal Components AnalysisΒΆ

This example is similar to the example scikit-learn Principal components analysis (PCA) . The red, green and blue axes represent the principal component axes. For clarity in the plot, the number data points, N, is 3000 versus 30000 as in the sckit-learn plot, and the axes are scaled.

../../_images/pca1.png
import numpy as np
import matplotlib.pyplot as plt
from matplotlib import cm
import s3dlib.surface as s3d

#.. Principal components analysis (PCA)

# 1. Define data to examine .........................................

np.random.seed(0)
N=3000
y = np.random.normal(scale=0.5, size=N)
x = np.random.normal(scale=0.5, size=N)
z = np.random.normal(scale=0.1, size=N)
a = x + y
b = 2 * y
c = a - b + z
norm = np.sqrt(a.var() + b.var())
a /= norm
b /= norm
data = np.transpose([ a,b,c ])

# 2. Setup and map surfaces .........................................

ellipsoid = s3d.SphericalSurface(3, color='darkgoldenrod', linewidth=0  )
plate     = s3d.PlanarSurface(3, color='darkgoldenrod', linewidth=0  )

# 3. Construct figures, add surfaces, and plot ......................
surfaces = [ plate, ellipsoid ]
elevazim = [ (-40,-80), (30,20) ]

fig = plt.figure(figsize=plt.figaspect(.5))
minmax=(-3,3)
for i in range(2) :
    surface = surfaces[i]
    ea = elevazim[i]
    # setup surfaces .......
    surface.map_geom_from_svd(data)
    tAxis = surface.get_transformAxis(lenmult=[2.3,2.5,-20])
    surface.transform(scale=2).set_surface_alpha(.2)
    # .....................
    ax = fig.add_subplot(121+i, projection='3d')
    ax.set(xlim=minmax, ylim=minmax, zlim=minmax)
    ax.scatter(a,b,c, c='k', marker='.', s=1)
    ax.view_init(*ea)
    ax.axes.xaxis.set_ticklabels([])
    ax.axes.yaxis.set_ticklabels([])
    ax.axes.zaxis.set_ticklabels([])
    ax.set_xlabel('X', labelpad=-10)
    ax.set_ylabel('Y', labelpad=-10)
    ax.set_zlabel('Z', labelpad=-10)
    ax.add_collection(surface)
    ax.add_collection3d(tAxis)

fig.tight_layout()

plt.show()

Alternative view of data in the principal component axes as:

../../_images/pca_axes.png
import numpy as np
import matplotlib.pyplot as plt
from matplotlib import cm
import s3dlib.surface as s3d
import copy

#.. Principal components axis plot (PCA)

# 1. Define data to examine .........................................

np.random.seed(0)
N=3000
y = np.random.normal(scale=0.5, size=N)
x = np.random.normal(scale=0.5, size=N)
z = np.random.normal(scale=0.1, size=N)
a = x + y
b = 2 * y
c = a - b + z
norm = np.sqrt(a.var() + b.var())
a /= norm
b /= norm
data = np.transpose([ a,b,c ])

# 2. Setup and map surfaces .........................................

ellipsoid = s3d.SphericalSurface(3, color='darkgoldenrod' )
ellipsoid.set_surface_alpha(.15)
ellipsoid.map_geom_from_svd(data)
tAxis =  ellipsoid.get_transformAxis(lenmult=[2.3,2.5,-20],negaxis=True)
matrix = ellipsoid.svd_dict['trans'][0]
ellipsoid.transform(scale=2)
x,y,z = data.T

transEllp = copy.copy(ellipsoid).transform(matrix.T)
xp,yp,zp = np.dot(data,matrix.T).T

# 3. Construct figures, add surfaces, and plot ......................

minmax,ticks,elaz = (-3,3),(-3,-2,-1,0,1,2,3), (35,-25)
fig = plt.figure(figsize=plt.figaspect(.5))

ax1 = fig.add_subplot(121, projection='3d')
ax1.set_title("Data Axes")
ax1.set( xlim=minmax, xticks=ticks, xlabel='X',
        ylim=minmax, yticks=ticks, ylabel='Y', 
        zlim=minmax, zticks=ticks, zlabel='Z' )     
ax1.view_init(*elaz)
ax1.set_proj_type('ortho')
ax1.add_collection3d(tAxis)
ax1.scatter(x,y,z, c='k', marker='.', s=1)
ax1.add_collection3d(ellipsoid.shade(0.7))

ax2 = fig.add_subplot(122, projection='3d')
ax2.set_title("Principal Axes")
ax2.set( xlim=[np.min(xp),np.max(xp)], 
        ylim=[np.min(yp),np.max(yp)], 
        zlim=[np.min(zp),np.max(zp)]  )     
ax2.tick_params("x",  colors='r')
ax2.set_xlabel(r'$X_{pc}$', color='r')
ax2.tick_params("y",  colors='g')
ax2.set_ylabel(r'$Y_{pc}$', color='g')
ax2.tick_params("z",  colors='b')
ax2.set_zlabel(r'$Z_{pc}$', color='b')
ax2.view_init(*elaz)
ax2.set_proj_type('ortho')
s3d.setupAxis(ax2, length=[3.5,2.5,.15], width=1.5, negaxis=True, 
                  alr=0, color=['r','g','b'], labels='' )
ax2.scatter(xp,yp,zp, c='k', marker='.', s=1)
ax2.add_collection3d(transEllp.shade(0.7))

fig.tight_layout()
plt.show()