Skip to content

Commit 338efda

Browse files
author
deepshekhardas
committed
fix: correct Spearman correlation for tied values
1 parent c0db072 commit 338efda

1 file changed

Lines changed: 25 additions & 10 deletions

File tree

maths/spearman_rank_correlation_coefficient.py

Lines changed: 25 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -1,26 +1,35 @@
11
from collections.abc import Sequence
22

33

4-
def assign_ranks(data: Sequence[float]) -> list[int]:
4+
def assign_ranks(data: Sequence[float]) -> list[float]:
55
"""
6-
Assigns ranks to elements in the array.
6+
Assigns ranks to elements in the array, using averaged ranks for ties.
77
88
:param data: List of floats.
9-
:return: List of ints representing the ranks.
9+
:return: List of floats representing the ranks.
1010
1111
Example:
1212
>>> assign_ranks([3.2, 1.5, 4.0, 2.7, 5.1])
13-
[3, 1, 4, 2, 5]
13+
[3.0, 1.0, 4.0, 2.0, 5.0]
1414
1515
>>> assign_ranks([10.5, 8.1, 12.4, 9.3, 11.0])
16-
[3, 1, 5, 2, 4]
16+
[3.0, 1.0, 5.0, 2.0, 4.0]
17+
18+
>>> assign_ranks([1.0, 2.0, 2.0, 4.0])
19+
[1.0, 2.5, 2.5, 4.0]
1720
"""
21+
n = len(data)
1822
ranked_data = sorted((value, index) for index, value in enumerate(data))
19-
ranks = [0] * len(data)
20-
21-
for position, (_, index) in enumerate(ranked_data):
22-
ranks[index] = position + 1
23-
23+
ranks = [0.0] * n
24+
i = 0
25+
while i < n:
26+
j = i
27+
while j < n - 1 and ranked_data[j + 1][0] == ranked_data[i][0]:
28+
j += 1
29+
avg_rank = (i + j) / 2.0 + 1
30+
for k in range(i, j + 1):
31+
ranks[ranked_data[k][1]] = avg_rank
32+
i = j + 1
2433
return ranks
2534

2635

@@ -50,8 +59,14 @@ def calculate_spearman_rank_correlation(
5059
>>> y = [5, 1, 2, 9, 5]
5160
>>> calculate_spearman_rank_correlation(x, y)
5261
0.6
62+
>>> calculate_spearman_rank_correlation([1], [1])
63+
Traceback (most recent call last):
64+
...
65+
ValueError: Need at least 2 data points
5366
"""
5467
n = len(variable_1)
68+
if n < 2:
69+
raise ValueError("Need at least 2 data points")
5570
rank_var1 = assign_ranks(variable_1)
5671
rank_var2 = assign_ranks(variable_2)
5772

0 commit comments

Comments
 (0)