2
$\begingroup$

I would like to know if there is a metric used to compute the similarity between two scatter plots?

$\endgroup$
  • $\begingroup$ Technically, "d(x,y) = 0 if x=y and 1 otherwise" is a distance function on scatterplots. So you need to define properties that the similarity should have. For example, is a 45 degree rotated scatterplot similar? $\endgroup$ – Has QUIT--Anony-Mousse Jun 13 '18 at 20:07
2
$\begingroup$

The simplest method is to calculate the euclidean distance between the baricenters of the two distributions; This do not take in account of the variance between the distributions, however.

If you want something more accurate, you can add to that distance the spread of the distributions; between the others, you can calculate the spread as the standard deviation of the distances between the baricenter (already calculated) and each of the points.

You can also think of using a join metric of the first two (baricenter distance and spread distance).

An example in Python. Take the three distributions in the image: The dummy distribution created

As you can see, distribution A and B are centered around the same point, but they have different spreads. Distribution A and C have different centers, but their spreads are more similar.

Here the code to calculate the distances I described. The more the distances are small, the more the distributions are similar.

#create three dummy distributions
dist_a=[]
dist_b=[]
dist_c=[]
for i in range (100):
    dist_a.append(np.random.randn(2)+10)
    dist_c.append(np.random.randn(2)+25)
    dist_b.append(np.random.randn(2)*5.5+10)

plt.scatter([a for a, _ in dist_a], [b for _, b in dist_a], label='distribution a')
plt.scatter([a for a, _ in dist_b], [b for _, b in dist_b], label='distribution b')
plt.scatter([a for a, _ in dist_c], [b for _, b in dist_c], label='distribution c')

plt.legend()

#calculate baricenters
bc_a=np.mean(dist_a, axis=0)
bc_b=np.mean(dist_b, axis=0)
bc_c=np.mean(dist_c, axis=0)

#calculate the distance between baricenters
dist_a_b=np.linalg.norm(bc_a-bc_b)
dist_a_c=np.linalg.norm(bc_a-bc_c)
dist_b_c=np.linalg.norm(bc_b-bc_c)

print("baricenter distante between distribution A and distribution B=", dist_a_b)
print("baricenter distante between distribution A and distribution C=", dist_a_c )
print("baricenter distante between distribution B and distribution C=", dist_b_c )
print ("\n")

#calculate the spread of the distributions, e.g. their standard deviation
spread_a=np.std(dist_a)
spread_b=np.std(dist_b)
spread_c=np.std(dist_c)


dist_spread_a_b=np.abs(spread_a-spread_b)
dist_spread_a_c=np.abs(spread_a-spread_c)
dist_spread_b_c=np.abs(spread_b-spread_c)

print("spread distance between distribution A and distribution B=", dist_spread_a_b)
print("spread distance between distribution A and distribution C=", dist_spread_a_c)
print("spread distance between of distribution B and distribution C=", dist_spread_b_c)
print ("\n")

#put in a single metric. NB, the paramenter of this join is subjective, and depend on the usecase
#alpha=0 : don't care about the euclidean distance between the baricenters
#alpha=1 : don't care about the spread distance between the baricenters

alpha=0.3
joint_metric_a_b=alpha*dist_a_b + (1-alpha)*dist_spread_a_b
joint_metric_a_c=alpha*dist_a_c + (1-alpha)*dist_spread_a_c
joint_metric_b_c=alpha*dist_b_c + (1-alpha)*dist_spread_b_c


print("joined metric distance between distribution A and distribution B=", joint_metric_a_b)
print("joined metric distance between distribution A and distribution C=", joint_metric_a_c)
print("joined metric distance between distribution B and distribution C=", joint_metric_b_c)

Outputs:

baricenter distante between distribution A and distribution B= 0.22454217332627005
baricenter distante between distribution A and distribution C= 21.028862497007008
baricenter distante between distribution B and distribution C= 20.98580645790957


spread distance between distribution A and distribution B= 4.153324630270008
spread distance between distribution A and distribution C= 0.004700454831506384
spread distance between of distribution B and distribution C= 4.158025085101515


joined metric distance between distribution A and distribution B= 2.974689893186887
joined metric distance between distribution A and distribution C= 6.311949067484157
joined metric distance between distribution B and distribution C= 9.206359496943932

Following the first metric (euclidean distance between baricenters), distribution A and B are more similar.

Following the second metric (spread distance), distribution A and C are more similar.

The third metric is tunable, by the parameter alpha, which accept values between 0 and 1. Depending on your usecase, you can be more interested that the distributions lie around the same point, and so you care more on the distance between their baricenters, or that the distributions have the same spread, even if their baricenters are slightly displaced. So, you have to adapt the paramenter alpha to your case.

|improve this answer|||||
$\endgroup$
1
$\begingroup$

A fast method with minimal preprocessing would be to convert scatterplots to 2D histograms and then compare the histograms based on their distance. Histogram distance metrics (such as Hellinger distance) are described in this post: https://datascience.stackexchange.com/a/33007/52089.

The smaller the distance between the histograms, the higher the similarity of the scatterplots :)

|improve this answer|||||
$\endgroup$

Not the answer you're looking for? Browse other questions tagged or ask your own question.