Source code for pydl.pcomp
# Licensed under a 3-clause BSD style license - see LICENSE.rst
# -*- coding: utf-8 -*-
import numpy as np
from astropy.utils import lazyproperty
[docs]
class pcomp(object):
"""Replicates the IDL ``PCOMP()`` function.
The attributes of this class are all read-only properties, implemented
with :class:`~astropy.utils.decorators.lazyproperty`.
Parameters
----------
x : array-like
A 2-D array with :math:`N` rows and :math:`M` columns.
standardize : :class:`bool`, optional
If set to ``True``, the input data will have its mean subtracted off
and will be scaled to unit variance.
covariance : :class:`bool`, optional.
If set to ``True``, the covariance matrix of the data will be used for
the computation. Otherwise the correlation matrix will be used.
Notes
-----
References
----------
https://www.nv5geospatialsoftware.com/docs/pcomp.html
Examples
--------
"""
def __init__(self, x, standardize=False, covariance=False):
from scipy.linalg import eigh
if x.ndim != 2:
raise ValueError('Input array must be two-dimensional')
no, nv = x.shape
self._nv = nv
if standardize:
xstd = x - np.tile(x.mean(0), no).reshape(x.shape)
s = np.tile(xstd.std(0), no).reshape(x.shape)
self._array = xstd/s
self._xstd = xstd
else:
self._array = x
self._xstd = None
self._standardize = standardize
if covariance:
self._c = np.cov(self._array, rowvar=0)
else:
self._c = np.corrcoef(self._array, rowvar=0)
self._covariance = covariance
#
# eigh is used for symmetric matrices
#
evals, evecs = eigh(self._c)
#
# Sort eigenvalues in descending order
#
ie = evals.argsort()[::-1]
self._evals = evals[ie]
self._evecs = evecs[:, ie]
#
# If necessary, add code to fix the signs of the eigenvectors.
# http://www3.interscience.wiley.com/journal/117912150/abstract
#
return
@lazyproperty
def coefficients(self):
"""(:class:`~numpy.ndarray`) The principal components.
These are the coefficients of `derived`.
Basically, they are a re-scaling of the eigenvectors.
"""
return self._evecs * np.tile(np.sqrt(self._evals), self._nv).reshape(
self._nv, self._nv)
@lazyproperty
def derived(self):
"""(:class:`~numpy.ndarray`) The derived variables.
"""
derived_data = np.dot(self._array, self.coefficients)
if self._standardize:
derived_data += self._xstd
return derived_data
@lazyproperty
def variance(self):
"""(:class:`~numpy.ndarray`) The variances of each derived variable.
"""
return self._evals/self._c.trace()
@lazyproperty
def eigenvalues(self):
"""(:class:`~numpy.ndarray`) The eigenvalues.
There is one eigenvalue for each principal component.
"""
return self._evals