How can I make sure that the means can be seen to form an approximate eq triangle, after generating 3 off 2D norm distr with 1000 points each

Viewed 53

I generate three 2D normally distributed distributions with 1000 points each with different means and variances and made sure there is some overlap between the three distributions by visualising the distributions.

dist1= 10 + 5 * np.random.randn(1000,1)
dist2= 15 + 20 * np.random.randn(1000,1)
dist3= 20 + 5 * np.random.randn(1000,1)

Also, the exercise is asking to make sure that the means can be seen to form an approximate equilateral triangle, so I have done this

plt.hist(dist1, bins="auto", stacked =True, alpha=0.3)
plt.axvline(dist1.mean(), color='k', linestyle='dashed', linewidth=1)
plt.hist(dist2, bins="auto", stacked =True, alpha=0.3)
plt.axvline(dist2.mean(), color='k', linestyle='dashed', linewidth=1)
plt.hist(dist3, bins="auto", stacked =True, alpha=0.3)
plt.axvline(dist3.mean(), color='k', linestyle='dashed', linewidth=1)
plt.show()

Would this be the right approach? I am not sure how to create 3 lines so that it shows a triangle

I have also tried this:

D1 = np.random.normal(1.1,5, 1000)
D2 = np.random.normal(1.05,4, 1000)
D3 = np.random.normal(1,3, 1000)

x=np.average(D1)
y=np.average(D2)
z=np.average(D3)

print('')

plt.scatter(x,y)
plt.scatter(y,z)
plt.scatter(z,x)

plt.plot((x,y),(y,z),'-r')
plt.plot((y,z),(z,x),'-p')
plt.plot((z,x),(x,y),'y')

print('')

So I could see the triangle, but not sure.

1 Answers

For a 2D distribution, the arrays need to have a shape of (N,2). A shape of (N,1) is only 1D. To form an equilateral triangle, the third center could be at D*sqrt(3)/2 above the middle point of the two other centers (with D the distance between them). You could visualize the points via plt.scatter(dist1[:,0], dist1[:,1]) (dist1[:,0] would be the x-coordinates, dist1[:,1] the y-coordinates).

from matplotlib import pyplot as plt
import numpy as np

dist1 = np.random.randn(10000, 2) * 5 + np.array([10, 10])
dist2 = np.random.randn(10000, 2) * 10 + np.array([30, 10])
dist3 = np.random.randn(10000, 2) * 7 + np.array([20, 10 + np.sqrt(400 / 3)])

plt.scatter(dist1[:, 0], dist1[:, 1], color='r', alpha=0.1, s=1)
plt.scatter(dist2[:, 0], dist2[:, 1], color='g', alpha=0.1, s=1)
plt.scatter(dist3[:, 0], dist3[:, 1], color='b', alpha=0.1, s=1)

center1 = dist1.mean(axis=0)
center2 = dist2.mean(axis=0)
center3 = dist3.mean(axis=0)
plt.plot([center1[0], center2[0], center3[0], center1[0]],
         [center1[1], center2[1], center3[1], center1[1]],
         lw=3, ls='--', color='gold')
plt.axis('equal')
plt.show()

3 2D normal distributions

To concatenate the arrays, and assign a label to each part, you could use:

from matplotlib import pyplot as plt
import numpy as np

dist1 = np.random.randn(10000, 2) * 5 + np.array([10, 10])
dist2 = np.random.randn(10000, 2) * 10 + np.array([30, 10])
dist3 = np.random.randn(10000, 2) * 7 + np.array([20, 10 + np.sqrt(400 / 3)])
dist4 = np.concatenate([dist1, dist2, dist3])
class_label = np.repeat([1, 2, 3], [dist1.shape[0], dist2.shape[0], dist3.shape[0]])
plt.scatter(dist4[:, 0], dist4[:, 1], c=class_label, cmap='tab10', alpha=0.1, s=1)
plt.show()

You could also add the labels as a third dimension:

dist4_with_label = np.hstack([dist4, class_label.reshape(-1, 1)])
plt.scatter(dist4_with_label[:, 0], dist4_with_label[:, 1], c=dist4_with_label[:, 2],
            cmap='tab10', alpha=0.1, s=1)
Related