# Intuition on Wasserstein Distance

I've been trying to familiarize myself with the Wasserstein distance and saw this answer on StackExchange by @antike that at first made a lot of sense, but then it didn't (to me, of course).

In the chart, you can see distributions where one group accounts for 60% of items (leftmost bar), and 4 more groups account for 10% each. Then the idea is that if you want to move the 60% bar to one spot to the right, the cost is 0.5, and if you want to move it 4 spots to the right the cost is 0.5*4=2.

That makes a lot of sense and easy to intuitively understand. But then things got complicated.

if you from scipy.stats import wasserstein_distance and calculate the distance between a vector like [6,1,1,1,1] and any permutation of it where the 6 "moves around", you would get (1) the same Wasserstein Distance, and (2) that would be 0.

I don't understand why either (1) and (2) occur, and would love your help understanding. If I have 10 pebbles in piles lined on a row, 6 stacked in the first position 4 more piles of 1 pebble, and I wanted to make the second pile have 6 pebbles instead of the first one, then I would need to do an amount of work which is 5 - which is 5 times moving 1 pebble one position.

Edit: some code:

from scipy.stats import wasserstein_distance
import numpy as np

a = np.array([6,1,1,1,1])
b = np.array([1,6,1,1,1])
c = np.array([1,1,6,1,1])

print(wasserstein_distance(a,b))
print(wasserstein_distance(a,c))
print(wasserstein_distance(b,c))
print(wasserstein_distance(a/10,b/10))
print(wasserstein_distance(b/10,c/10))
print(wasserstein_distance(a*10,b*10))
print(wasserstein_distance(a*10,b*10))
print(wasserstein_distance([6,1,1,1,1],[1,1,1,1,6]))


all of these print 0. Would love to be shown I was making a foolish mistake.

• That sounds strange and should not happen. Can you edit your post to include a Minimal Working Example exhibiting the problem? Incidentally, that interpretation motivates the common name "Earth Mover's Distance" for the Wasserstein metric. – Stephan Kolassa Apr 12 at 12:24
• I'd also think that the problem seems to be with your "scipy.stats" (not sure what that is) coding rather than with the Wasserstein distance itself. Nothing wrong with your intuition as far as you have explained it. – Lewian Apr 12 at 12:44
• Thank you @StephanKolassa and Lewian. Added a MWE. :) – Optimesh Apr 12 at 12:57

Here is the documentation:

Parameters
u_values, v_values array_like
Values observed in the (empirical) distribution.


Note that wasserstein_distance expects the observed values. You provided a table of the values. Thus, [6,1,1,1,1] is interpreted as "once the observations 6 and four times 1", precisely the same as [1,6,1,1,1].

To get what you want, you need to provide the underlying values, and then you do see a more reasonable result.

wasserstein_distance([1,1,1,1,1,1,2,3,4,5],[1,2,2,2,2,2,2,3,4,5]) # Result 0.5
wasserstein_distance([1,1,1,1,1,1,2,3,4,5],[1,2,3,3,3,3,3,3,4,5]) # Result 1.0

• Thank you very much for replying. I think that directionally I understand what you mean: I gave values instead of distribution (where the location of the 6 would matter). I cannot follow your examples though - would you mind running them with my example in mind? Essentially, I'm looking at the relative distribution of 5 items, a to e where one of them appears 60% of the time, and the other 4 10% of the time each. Then I want to move the 60% to b, then c etc and see how the WD changes. I think it should be 0.5, 1, 1.5 and so on. Thanks again! – Optimesh Apr 12 at 13:57
• The first one of the two examples at the bottom of my post corresponds to having six times a and b through e once each, compared to having one each of a, c, d and e and six bs. The distance is 0.5. The second example compares "six times a, one each of b through e" to "six times c, one each of a, b, d and e", with a distance of 1.0. Essentially, the numbers are the position of each letter in the alphabet. (And writing the letters would require lots of tickmarks.) – Stephan Kolassa Apr 12 at 14:04
• Ah, I see what you mean now! I was expecting the value of the elements to matter. So what do I do then, if for example I want to compare the distribution of [20,30,40] (the values 20, 30 and 40 each appear once) to let's say [20,70,100] (each appears once) ? – Optimesh Apr 12 at 14:15
• wasserstein_distance([20,30,40],[20,70,100]) yields a result of 33.33, looks good! – Stephan Kolassa Apr 12 at 14:24
• Nice, thank you Stephan! – Optimesh Apr 12 at 14:30