natural language toolkit spearman rank correlation c 20012023 nltk project joel nothman jnothmanstudent usyd edu au url https www nltk org for license information see license txt tools for comparing ranked lists finds the difference between the values in ranks1 and ranks2 for keys present in both dicts if the arguments are not dicts they are converted from key rank sequences returns the spearman correlation coefficient for two rankings which should be dicts or sequences of key rank the coefficient ranges from 1 0 ranks are opposite to 1 0 ranks are identical and is only calculated for keys in both rankings for meaningful results remove keys present in only one list before ranking n 0 res 0 for k d in rankdistsranks1 ranks2 res d d n 1 try return 1 6 res n n n 1 except zerodivisionerror result is undefined if only one item is ranked return 0 0 def ranksfromsequenceseq return k i for i k in enumerateseq def ranksfromscoresscores rankgap1e15 prevscore none rank 0 for i key score in enumeratescores try if absscore prevscore rankgap rank i except typeerror pass yield key rank prevscore score natural language toolkit spearman rank correlation c 2001 2023 nltk project joel nothman jnothman student usyd edu au url https www nltk org for license information see license txt tools for comparing ranked lists finds the difference between the values in ranks1 and ranks2 for keys present in both dicts if the arguments are not dicts they are converted from key rank sequences returns the spearman correlation coefficient for two rankings which should be dicts or sequences of key rank the coefficient ranges from 1 0 ranks are opposite to 1 0 ranks are identical and is only calculated for keys in both rankings for meaningful results remove keys present in only one list before ranking result is undefined if only one item is ranked given a sequence yields each element with an increasing rank suitable for use as an argument to spearman_correlation given a sequence of key score tuples yields each key with an increasing rank tying with previous key s rank if the difference between their scores is less than rank_gap suitable for use as an argument to spearman_correlation
def _rank_dists(ranks1, ranks2):
    
    ranks1 = dict(ranks1)
    ranks2 = dict(ranks2)
    for k in ranks1:
        try:
            yield k, ranks1[k] - ranks2[k]
        except KeyError:
            pass


def spearman_correlation(ranks1, ranks2):
    
    n = 0
    res = 0
    for k, d in _rank_dists(ranks1, ranks2):
        res += d * d
        n += 1
    try:
        return 1 - (6 * res / (n * (n * n - 1)))
    except ZeroDivisionError:
        
        return 0.0


def ranks_from_sequence(seq):
    
    return ((k, i) for i, k in enumerate(seq))


def ranks_from_scores(scores, rank_gap=1e-15):
    
    prev_score = None
    rank = 0
    for i, (key, score) in enumerate(scores):
        try:
            if abs(score - prev_score) > rank_gap:
                rank = i
        except TypeError:
            pass

        yield key, rank
        prev_score = score