liveBook · Manning

Spearman's rank correlation coefficient

As explained in Outlier Detection in Python

Spearman correlation is a rank-based measure of the strength and direction of a monotonic association between two variables.

Spearman correlation measures association using the rank order of two sets of values: it is Pearson correlation calculated on their ranks rather than their raw values. This makes it useful when two outlier detectors order records similarly but produce scores on different distributions. Raw-score Pearson correlation can be weak even when the rankings agree. section 8.4

For detector evaluation, the question is often whether detectors identify and rank the same outliers—not whether they agree about ordinary records. Correlating every score can let numerous low-scoring records obscure that question. One approach keeps records placed in at least one detector’s top 5%, then compares scores on that subset. Another ranks each detector’s scores and sets ranks outside its top 5% to zero. The cutoff is a choice, not a universal rule. section 8.4

Listing 8.6 Cleaning the outlier scores to calculate their correlation
top_scores_df = scores_df[scores_cols].copy()
for col_name in top_scores_df.columns: 
  top_scores_df[col_name] = top_scores_df[col_name].rank()
  top_scores_df[col_name] = top_scores_df[col_name].apply(
      lambda x: x if x > (len(df) * 0.95) else 0.0)

The listing ranks each detector’s scores and zeroes ranks below the top-5% threshold before correlation. section 8.4

Spearman correlation also helps construct feature subspaces. For numeric features, calculate pairwise correlations, begin a subspace with a strongly associated pair, and add features strongly associated with those already selected. Keeping associated features together can make departures from their usual relationship visible. Spearman correlation misses nonmonotonic relationships; predictive models can capture more complex associations. section 10.1.2

Baseball feature subspace

At bats and Runs have a reported correlation of 0.94 in the baseball data. Grouping them in a feature subspace preserves a strong observed association; records that depart substantially from it may be outliers. section 10.1.2

Listing 10.3 Example code to identify subspaces based on correlations
def get_highest_corr():                                           #1
    return np.unravel_index(
        np.argmax(corr_matrix.values, axis=None), 
        corr_matrix.shape)
 
def get_correlated_subspaces(corr_matrix, num_base_detectors, 
                                num_feats_per_detector):
    sets = []
    for _ in range(num_base_detectors):                           #2
        m1, m2 = get_highest_corr()
        curr_set = [m1, m2]                                       #3
        for _ in range(2, num_feats_per_detector):
            m = np.unravel_index(np.argsort(corr_matrix.values, axis=None), 
                                 corr_matrix.shape)               #4
            m0 = m[0][::-1]
            m1 = m[1][::-1]
            for i in range(len(m0)):
                d0 = m0[i]
                d1 = m1[i]
                if (d0 in curr_set) or (d1 in curr_set):          #5
                    curr_set.append(d0)
                    curr_set = list(set(curr_set))
                    if len(curr_set) < num_feats_per_detector:
                        curr_set.append(d1)
                        curr_set = list(set(curr_set))            #6
                if len(curr_set) >= num_feats_per_detector:
                    break
 
            for i in curr_set:                                    #7
                i_idx = corr_matrix.index[i]
                for j in curr_set:
                    j_idx = corr_matrix.columns[j]
                    corr_matrix.loc[i_idx, j_idx] = 0
            if len(curr_set) >= num_feats_per_detector:
                break
 
        sets.append(curr_set)
    return sets
 
import pandas as pd
import numpy as np
from sklearn.datasets import fetch_openml
 
data = fetch_openml('baseball', version=1)
df = pd.DataFrame(data.data, columns=data.feature_names)
 
corr_matrix = abs(df.corr(method='spearman'))
corr_matrix = corr_matrix.where(
    np.triu(np.ones(corr_matrix.shape), k=1).astype(np.bool))
corr_matrix = corr_matrix.fillna(0)
 
feat_sets_arr = get_correlated_subspaces(corr_matrix, num_base_detectors=5, 
                                         num_feats_per_detector=4)
for feat_set in feat_sets_arr:    
    print([df.columns[x] for x in feat_set])

The listing implements subspace selection from a feature-correlation matrix, starting with a highly correlated pair and adding associated features. section 10.1.2

How Outlier Detection in Python covers it

How deep it goes
Defines correlation of ranks and demonstrates score filtering and feature grouping, without deriving a coefficient formula.
Examples
Uses abalone detector scores and baseball features, including the reported 0.94 correlation between At bats and Runs.
What it assumes
Assumes familiarity with tabular scores and numeric features while defining rank correlation through its contrast with raw-score Pearson correlation.
What you can do after
Apply it via pandas to compare detector rankings or construct correlation-guided feature subspaces.
How it connects
Connects Pearson correlation and rank ordering to outlier detection, feature subspaces, and monotonic relationships.

Also explained in

Compare how 2 books explain Spearman's rank correlation coefficient →

Related concepts

This explainer was generated by Manning's knowledge graph from the text of Outlier Detection in Python. The section links point to the parts of the book it draws on.