opened
erelsgl
username_0
0.33333333333333337
Kendall tau distance
issue
created
josef-pkt
username_1
array([[1, 3],
       [2, 2],
       [3, 1]])
```
comment
created
josef-pkt
username_1
maybe that doesn't answer the issue, I'm thinking of spearman and don't have much intuition for kendall
comment
created
mirca
username_2
Hi @username_0, the results looks correct. In your first example you have ``x = [1, 3, 2]`` and ``y = [3, 1, 2]`` which gives ``#{discordant pairs} = 3``, ``#{concordant pairs} = 0``, resulting in ``tau = (0 - 3) / 3 = -1``. In the second example, ``x = [1, 3, 2]`` and ``y = [1, 2, 3]``, so ``#{discordant pairs} = 1 `` and ``#{concordant pairs} = 2 ``, hence ``tau = (2 - 1) / 3 = 1 / 3``. 
 Take a look at https://en.wikipedia.org/wiki/Kendall_rank_correlation_coefficient
comment
created
erelsgl
username_0
Hmmm... the Wikipedia page on https://en.wikipedia.org/wiki/Kendall_tau_distance says that "Kendall tau distance is also called bubble-sort distance since it is equivalent to **the number of swaps that the bubble sort algorithm would make to place one list in the same order as the other list**".  The number of swaps in my example is obviously small (1), while the number of discordant pairs is large (3). They are not the same. Is this a mistake in the Wikipedia page?
comment
created
evgenyzhurko
username_3
Kendall rank correlation coefficient and Kendall tau distance are the different measurement.

@username_0 say true information about Kendall tau distance. `kendall_tau_distance = m / (n * (n - 1) / 2)`, where `m` - pairs whose values are in opposite order and `n` - size of list. As a result, Kendall tau distance therefore lies in the interval `[0,1]`, because `m` in  never less than `0`.

@username_2 also say true information, but about Kendall rank correlation coefficient. `kendall_tau_correlation = (p - q) / (n * (n - 1) / 2)`, where `p` - number of concordant pairs, `q` - number of discordant pairs, `n` - size of list. `kendall_tau_correlation` lies in the interval `[-1;1]`.

scipy.stats.kendall tau is a function to find Kendall rank correlation coefficient but not for Kendall tau distance. I didn't find the implementation of Kendall tau distance in SciPy.

If the implementation is not exist in SciPy actually, I can implement it.
comment
created
masdeseiscaracteres
username_4
Hi all! Interesting discussion. For those interested (and answering @username_0 question) I wrote a post trying to shed some light on what is going on with the Kendall Tau distance and the Wikipedia page.  Basically the confusion roots in two distinct usages of the word "ranking". Sometimes it refers to "ranking lists", and, some others, to "ranked lists of items". We get weird results when the type of "ranking" we have at hand does not match the one used in the definition we are applying.
comment
created
sina-mansour
username_5
Hi all, 

I was just reading this thread and noticed a **major misunderstanding** in the very definition of Kendall's tau.

There are two distinct concepts, Kendall's tau **distance** and **correlation**. To give a clear reference to an article that defines both have a look at [this paper](https://arxiv.org/pdf/1905.02752.pdf) (pages 3-4)

---

These definitions are computed mainly by two values:

**Concordant pairs**: Pairs with conforming orders between permutations

![image](https://user-images.githubusercontent.com/16105138/81886891-33f38900-95e1-11ea-8763-9a2a886dd005.png)

And **Discordant pairs**: Pairs with opposing (inverse) orders between permutations

![image](https://user-images.githubusercontent.com/16105138/81886910-4077e180-95e1-11ea-9a21-5c21fef6b59f.png)

Having computed these two values,

The Kendall's tau **distance** (normalized) is computed by:

![image](https://user-images.githubusercontent.com/16105138/81886773-e414c200-95e0-11ea-86d3-6c90ac33411b.png)

The Kendall's tau rank **correlation** is computed by:

![image](https://user-images.githubusercontent.com/16105138/81886842-10304300-95e1-11ea-83d3-c2dc1ed76622.png)

---

To better clarify, let's take the example provided by @username_0.

We have two permutations: p1 = [1,3,2], and p2 = [3,1,2]

We have three pairs in the list: (1,2), (1,3), and (2,3)

We have two **concordant** pairs (C=1): (1,2) -> this means that the pair (1,2) appear in the same order in both permutations p1 & p2.

We have two **discordant** pairs (D=2): (1,3) & (2,3) these pairs have a different order across p1 & p2.

Thus, for our example:

Kendall's tau **distance** = 0.667

Kendall's tau rank **correlation** = - 0.333

---

**TLDR**

So as a brief conclusion, @username_0 is right in raising the issue, the current implementation is incorrect, as the definition of concordant and discordant pairs is not correctly implemented. as @username_3 also mentioned there's a difference between Kendall's tau distance and correlation. But it would be really easy to implement two functions that compute both.
comment
created
masdeseiscaracteres
username_4
KendalltauResult(correlation=-1.0, pvalue=0.3333333333333333)
```
#### So, what is the right way to look at the input parameters? 
We must think of `x` and `y` as coordinates of two data samples from which you compute your correlation coefficient. That is, we must think of Kendall's tau as a correlation coefficient in the same way you would do with [Pearson's r correlation coefficient](https://docs.scipy.org/doc/scipy/reference/generated/scipy.stats.pearsonr.html). They serve similar purposes, so they should be used similarly:

- Pearson's r:
  - Goal: quantify the extent to which the relationship between two data samples is **linear**.
  - Extreme values interpretation: 1 means a perfect increasing-slope linear relationship, -1 means a perfect decreasing-slope linear relationship.

- Kendall's tau 
  - Goal: quantify the extent to which the relationship between two data samples is **monotonic**.
  - Extreme values interpretation: 1 means a monotonically-increasing relationship, -1 means a monotonically-decreasing relationship.

Let's illustrate this with some examples. First, the one provided by @username_0:

```python
import matplotlib.pyplot as plt
from scipy.stats import kendalltau, pearsonr

def plot_data(x, y, labels):
    plt.scatter(x, y)
    for xi, yi, lab in zip(x, y, labels):
        plt.annotate(lab, (xi, yi), xytext=(3, 3), textcoords="offset points", ha='left', va='bottom')
    plt.axis([0, 4, 0, 4])

labels = ['A', 'B', 'C']

x = [1, 3, 2]
y = [3, 1, 2]

print("Pearson\'s r correlation coefficient: {:.2f}".format(pearsonr(x, y)[0]))
print("Kendall\'s tau correlation coefficient: {:.2f}".format(kendalltau(x, y)[0]))
plot_data(x, y, labels)
```
![image](https://user-images.githubusercontent.com/1186798/82152964-fbfc7800-9864-11ea-8387-5e34a4dc7757.png)


Then, let's modify it to keep the monotonicity but change the strength of the linear relationship:
```python
x = [1, 3, 2]
y = [3, 1, 2]
y[1] = 1.9 # we replace 1 by 1.9 in the second dataset

print("Pearson\'s r correlation coefficient: {:.2f}".format(pearsonr(x, y)[0]))  # linear relationship is now weaker
print("Kendall\'s tau correlation coefficient: {:.2f}".format(kendalltau(x, y)[0]))  # stays perfectly monotone
plot_data(x, y, labels)
```
![image](https://user-images.githubusercontent.com/1186798/82152982-0e76b180-9865-11ea-9b32-9e6559c60543.png)

As you can see, the results provided by the function are correct. We only need to interpret the input parameters differently (in the same way we do with Pearson's r).

#### What if we want to explain the results in terms of concordant & discordant pairs?
For counting the pairs, I'll use the fictitious labels (`'A', 'B', 'C'`) used in the plots above:

| label | A | B | C |
| - | - | - | - |
| coordinates 1 | 1.0 | 3.0 | 2.0 |
| coordinates 2 | 3.0 | 1.0 | 2.0 |

Now, sort the labels according to their coordinates (lower coordinates first):

| position (don't confuse with coordinates) | 1st | 2nd | 3rd |
| - | - | - | - |
| label ordering 1 | A | C | B |
| label ordering 2 | B | C | A |

Finally, count the number of concordant and discordant pairs:
- Discordant pairs (pairs whose elements order changed across orderings 1 and 2):
  - (A, B), (A, C) & (B, C). Three discordants pairs (D=3).
- Concordant pairs (pairs whose elements order stayed the same across orderings 1 and 2):
  - None. Three discordants pairs (D=3).

Therefore, if we now evaluate the formula (provided above by @username_5):
![](https://user-images.githubusercontent.com/16105138/81886842-10304300-95e1-11ea-83d3-c2dc1ed76622.png)
we get a Kendall's tau correlation coeffient = - 1.

## Summary
The current implementation **is not wrong** but the parameter interpretation may be ambiguous. It correctly provides the Kendall's tau rank correlation coefficient when passed two lists of element coordinates. It won't provide correct results when passed two lists of elements. It may be sufficient to clarify this extent through some disclaimer note or example. Also, providing another function for those willing to compute the Kendall's tau rank correlation from two lists of elements may be useful.

I agree with @username_5 that providing a function implementing the Kendall's tau rank distance it's simple and might be useful to clarify the difference between the two concepts.
comment
created
tupui
username_6
@username_5 @username_4 the PR addressing this is stalled. Feel free to drop in and add review the proposal so that it finally get merged.
comment
created
sina-mansour
username_5
I agree with @username_4 that by this interpretation the function does what it has to do. But I personally find the function ambiguous in its current form. I believe many users are actually interested to get to Kendall's correlation/distance from a permutation rather than rankings and the current description will not guide them towards the right solution.

Maybe if this was further clarified in the description this could avoid future confusion. On the other hand, one can use `np.argsort()` to convert a permutation to a ranking, this could either be added as a flag that the user selects (`kendalltau(x,y,from_permutations=True`) or at least as an example for people to know that if they are working with permutations they should feed `x=np.argsort(permutation)` to the function for it to work correctly.
comment