2
$\begingroup$

I am familiar with PCA from Making sense of principal component analysis, eigenvectors & eigenvalues where you either normalize the data (to standard normal or centered?) and construct a covariance matrix or just construct the correlation matrix, eigendecomposition, sort eigenvalue/vector pairs by eigenvalue in descending order (the ratio of these eigenvalues to their sum is the explained variance), and finally, transform the original data to be projected onto the new eigenvalue axes matmul(X, sorted_eigenvectors.T)

This makes sense to me but WHAT IS PRINCIPAL COORDINATE ANALYSIS? I understand you use a distance matrix instead of a correlation matrix. What does this mean in terms of eigenvectors? In PCA, the eigenvectors are in the direction of maximum variance but what about in a distance matrix space?

Here's some Python 3 code I made to do PCA.

import numpy as np
import pandas as pd
from sklearn.datasets import load_iris
from sklearn.preprocessing import StandardScaler
from sklearn import decomposition

np.random.seed(0)

# Iris dataset
DF_data = pd.DataFrame(load_iris().data, 
                       index = ["iris_%d" % i for i in range(load_iris().data.shape[0])],
                       columns = load_iris().feature_names)

Se_targets = pd.Series(load_iris().target, 
                       index = ["iris_%d" % i for i in range(load_iris().data.shape[0])], 
                       name = "Species")

# Correlation matrix (Note: StandardScaler of data and then covariance = correlation)
DF_corr = pd.DataFrame(np.corrcoef(DF_data.T), 
                      index = DF_data.columns,
                      columns = DF_data.columns)

# Eigendecomposition
Ve_eig_vals, Ar_eig_vecs = np.linalg.eig(DF_corr)

# Sorting eigenpairs
eig_pairs = [(np.fabs(Ve_eig_vals[j]), Ar_eig_vecs[:,j]) for j in range(DF_data.shape[1])]
eig_pairs.sort(); eig_pairs.reverse()
Ar_components = np.array([x[1] for x in eig_pairs])

# Projection matrix
Ar_Wproj = np.array([x[1] for x in eig_pairs]).T

DF_transformed = pd.DataFrame(np.matmul(DF_data.as_matrix(),Ar_Wproj),
                              columns=["PC_%d" % k for k in range(1, Ar_Wproj.shape[1]+1)])
#          PC_1      PC_2      PC_3      PC_4
# 0    2.669231 -5.180887 -2.506061 -0.115201
# 1    2.696434 -4.643645 -2.482874 -0.105533
# 2    2.481163 -4.752183 -2.304354 -0.102643
# 3    2.571512 -4.626615 -2.228277 -0.276660
# 4    2.590658 -5.236211 -2.409756 -0.153814
# 5    3.008099 -5.682217 -2.456525 -0.221893
# 6    2.490942 -4.908714 -2.106376 -0.181431
# 7    2.701455 -5.053209 -2.444074 -0.209103

Can I literally just replace the correlation matrix (DF_corr) w/ a distance matrix?

from scipy.spatial import distance

Ar_MxMdistance = distance.squareform(distance.pdist(DF_data.T, metric="braycurtis"))
DF_dism = pd.DataFrame(Ar_MxMdistance, index = DF_data.columns, columns = DF_data.columns)
$\endgroup$
3
  • 5
    $\begingroup$ PCoA, aka Torgerson's metric MDS, is quite transparently described in some answers to this question. I even tend to consider your question as a duplicate to it. Both @amoeba and me have explained there how PCoA is actually a PCA in its core. For example, in my answer find link to a document describing PCoA's math and link to an answer explaining "double centration" which is a switch from distances to scalar products of a centered "Gram matrix". The coordinates yielded by PCoA are actually "loadings" of the PCA performed on that matrix. $\endgroup$
    – ttnphns
    Jul 7 '16 at 22:36
  • $\begingroup$ What do you get when you do eigendecomposition on a distance matrix? $\endgroup$
    – O.rka
    Jul 13 '16 at 3:56
  • $\begingroup$ PCoA does not do eigendecomposition of a distance matrix. $\endgroup$
    – ttnphns
    Jul 13 '16 at 6:47