πŸŽ‰ 75% of content is free forever β€” Unlock Premium from $10/mo β†’
CW
Search courses…
πŸ’Ό Servicesℹ️ Aboutβœ‰οΈ ContactView Pricing Plansfrom $10

Correspondence Analysis

Advanced Statistical MethodsDimensionality Reduction🟒 Free Lesson

Advertisement

Introduction

Advanced Statistical Methods

Revealing Structure in Contingency Tables

Correspondence analysis decomposes contingency tables into principal coordinates, visualizing associations between row and column categories in a low-dimensional map. Chi-square distance drives the geometry.

  • Market research β€” Map relationships between product attributes and consumer preferences
  • Linguistics β€” Visualize word associations across different text corpora
  • Sociology β€” Explore associations between demographic categories and survey responses

CA turns cross-tabulated counts into revealing geometric maps of association.


Correspondence Analysis (CA) is a dimension reduction technique for categorical data contained in a contingency table. Developed primarily by Jean-Paul BenzΓ©cri (1973) and popularized by Greenacre (1984), CA decomposes the chi-square statistic into orthogonal components, yielding a low-dimensional geometric representation of rows and columns.

Unlike PCA, which operates on continuous data with Euclidean distance, CA uses the chi-square distance β€” a metric naturally suited to frequency data where the magnitude of counts varies across categories.

Simple Correspondence Analysis

The Contingency Table

Let be an contingency table with entries , row marginals , column marginals , and grand total .

Chi-Square Distance

The chi-square distance is symmetric and non-negative, and it equals zero if and only if the two row profiles are identical. The weighting by ensures that categories with small marginals are upweighted.

The Inertia Decomposition

Principal Coordinates

The standard coordinates are obtained by dividing principal coordinates by the square root of the eigenvalue:

Standard coordinates are used for plotting supplementary rows/columns.

The Symmetric Map

Contributions and Cosines

Multiple Correspondence Analysis

The Indicator Matrix

For categorical variables with levels each, define the indicator matrix of dimension where :

MCA is equivalent to CA of the Burt matrix :

Adjusted Inertia (Greenacre Correction)

The eigenvalues from MCA of the Burt matrix are inflated. Greenacre (1993) proposed the correction:

The total inertia in MCA equals for the indicator matrix (or for the Burt matrix before adjustment).

Factor Scores

Connection to Chi-Square Test

Python Implementation

import numpy as np
from prince import CA, MCA
import pandas as pd

# --- Simple Correspondence Analysis ---
# Create a contingency table (e.g., smoking by profession)
data = np.array([
    [4, 2, 3, 2, 3],  # Doctors
    [4, 3, 5, 5, 5],  # Lawyers
    [25, 10, 4, 6, 5], # Engineers
])
row_labels = ["Doctors", "Lawyers", "Engineers"]
col_labels = ["None", "Light", "Medium", "Heavy", "Very Heavy"]
df = pd.DataFrame(data, index=row_labels, columns=col_labels)

# --- Manual CA computation ---
def correspondence_analysis(N):
    I, J = N.shape
    n = N.sum()

    P = N / n
    r = P.sum(axis=1)   # row marginals
    c = P.sum(axis=0)   # column marginals

    # Standardized residuals
    E = np.outer(r, c)  # expected under independence
    S = (P - E) / np.sqrt(E)

    # Eigenvalue decomposition
    U, D, Vt = np.linalg.svd(S, full_matrices=False)
    lam = D**2

    # Principal coordinates
    F_row = np.diag(1.0 / np.sqrt(r)) @ U @ np.diag(np.sqrt(lam))
    F_col = np.diag(1.0 / np.sqrt(c)) @ Vt.T @ np.diag(np.sqrt(lam))

    # Contributions
    ctr_row = (r[:, None] * F_row**2) / lam[None, :]
    ctr_col = (c[:, None] * F_col**2) / lam[None, :]

    # Cosines (quality)
    cos2_row = F_row**2 / (F_row**2).sum(axis=1, keepdims=True)
    cos2_col = F_col**2 / (F_col**2).sum(axis=1, keepdims=True)

    # Total inertia
    total_inertia = lam.sum()
    chi2 = n * total_inertia

    return {
        'eigenvalues': lam,
        'total_inertia': total_inertia,
        'chi2': chi2,
        'row_coords': F_row,
        'col_coords': F_col,
        'row_contrib': ctr_row,
        'col_contrib': ctr_col,
        'row_cos2': cos2_row,
        'col_cos2': cos2_col,
    }

result = correspondence_analysis(data)
print("Eigenvalues:", result['eigenvalues'])
print("Total inertia:", result['total_inertia'])
print("Chi-square:", result['chi2'])
print("Row principal coords:\n", np.round(result['row_coords'], 4))
print("Column principal coords:\n", np.round(result['col_coords'], 4))
print("Row contributions:\n", np.round(result['row_contrib'], 4))

# --- Using prince library ---
ca = CA(n_components=2, n_iter=10, random_state=42)
ca.fit(df)

print("\n--- prince CA ---")
print("Eigenvalues:", ca.eigenvalues_)
print("Row coordinates:\n", ca.row_coordinates(df))
print("Column coordinates:\n", ca.column_coordinates(df))

# --- Multiple Correspondence Analysis ---
np.random.seed(42)
n = 200
mca_data = pd.DataFrame({
    'Education': np.random.choice(['HighSchool', 'Bachelor', 'Master', 'PhD'], n),
    'Region': np.random.choice(['North', 'South', 'East', 'West'], n),
    'Occupation': np.random.choice(['Engineer', 'Teacher', 'Doctor', 'Artist'], n),
})

mca = MCA(n_components=2, n_iter=10, random_state=42)
mca.fit(mca_data)
print("\n--- MCA ---")
print("Adjusted eigenvalues:", mca.eigenvalues_)
print("Row coordinates shape:", mca.row_coordinates(mca_data).shape)

# --- Symmetric map coordinates ---
def symmetric_map(N):
    I, J = N.shape
    n = N.sum()
    P = N / n
    r = P.sum(axis=1)
    c = P.sum(axis=0)

    # Row standard coordinates
    F_row_std = np.diag(1.0 / np.sqrt(r)) @ (P - np.outer(r, c)) @ np.diag(1.0 / np.sqrt(c))

    # SVD
    U, D, Vt = np.linalg.svd(F_row_std, full_matrices=False)
    lam = D**2

    # Symmetric coordinates
    F_sym = np.diag(np.sqrt(r)) @ U
    G_sym = np.diag(np.sqrt(c)) @ Vt.T

    return F_sym, G_sym, lam

F_sym, G_sym, lam = symmetric_map(data)
print("\nSymmetric row coords:\n", np.round(F_sym, 4))
print("Symmetric col coords:\n", np.round(G_sym, 4))

Interpretation Rules

Extensions

Canonical Correspondence Analysis (CCA) combines CA with constrained ordination, relating community composition to environmental variables. Non-symmetric correspondence analysis decomposes the statistic asymmetrically, focusing on how column categories explain row categories (or vice versa). Joint correspondence analysis maximizes the off-diagonal blocks of the Burt matrix, reducing the inflation effect without the algebraic correction.

Need Expert Statistics Help?

Get personalized tutoring, project support, or professional consulting.

Advertisement