Generation of arbitrary gaussian distributions

This is a memorandum to remind myself how the code of arbitrary gaussian distribution generation works.

To generate multiple gaussian distributions, it's a good idea to employ trigonometric functions.

```python
from math import cos, sin
import numpy as np
import matplotlib.pyplot as plt

# prepare variables
label = 1 # index of an individual distribution
n_labels = 6 # total number of distributions
x = np.random.normal(0, 1, (1000,1)) # x coord. of random numbers 
y = np.random.normal(0, 1, (1000,1)) # y coord. of random numbers

# define the angle for each distribution 
r = 2.0 * np.pi / float(n_labels) * float(label)
```

To stretch and tile the distribution, you can do this:

```python
new_x = x * cos(r) - y * sin(r)
plt.figure(figsize=(3, 3))
plt.scatter(x, y, s=2)
plt.scatter(new_x, y, s=2)
plt.legend(['original', 'stretch&tilted'])
plt.show()
```

then, you'll get following result:
![Figure_13.png](https://qiita-image-store.s3.amazonaws.com/0/345318/3931e4f9-d040-5b19-ecb9-4a90b051d497.png)
You can do the same to y coordinate as well.

```python
new_y = x * sin(r) + y * cos(r)
plt.figure(figsize=(3, 3))
plt.scatter(x, y, s=2)
plt.scatter(x, new_y, s=2)
plt.legend(['original', 'stretch&tilted'])
plt.show()
```

![Figure_13.png](https://qiita-image-store.s3.amazonaws.com/0/345318/a64c3e95-5793-f132-2820-bbd7c2beac42.png)
If you use both new_x and new_y, the distribution will be a normal one.

```python
plt.figure(figsize=(3, 3))
plt.scatter(x, y, s=2)
plt.scatter(new_x, new_y, s=2)
plt.legend(['original', 'stretch&tilted'])
plt.show()
```

![Figure_13.png](https://qiita-image-store.s3.amazonaws.com/0/345318/44d01573-edaf-cb89-1d48-f3eeec3ff0bf.png)
This is useful when the standard deviations of the distribution in x and y coordinates are different.

```python
x1 = np.random.normal(0, 1, (1000,1)) 
y1 = np.random.normal(0, 0.2, (1000,1))
new_x1 = x1 * cos(r) - y1 * sin(r)
new_y1 = x1 * sin(r) + y1 * cos(r)

plt.figure(figsize=(3, 3))
plt.scatter(x1, y1, s=2)
plt.scatter(new_x1, new_y1, s=2)
plt.legend(['original', 'rotated'])
plt.show()
```

![Figure13.png](https://qiita-image-store.s3.amazonaws.com/0/345318/b22e6044-7e08-569b-a4a7-b93f9fbad0e0.png)
You can add some shift to the whole distribution towards a certain direction defined by r that we have defined previously.

```python
shift = 2 # the amount of shift
new_x += shift * cos(r) # parallel shift to the direction of r
new_y += shift * sin(r) # parallel shift to the direction of r
```

![Figure_13.png](https://qiita-image-store.s3.amazonaws.com/0/345318/5abd71dd-c381-c338-4f1c-dbc07c96128a.png)

You can make it as a function for convenience.

```python
def sample(x, y, label, n_labels, shift):
    r = 2.0 * np.pi / float(n_labels) * float(label)
    new_x = x * cos(r) - y * sin(r) # change the slope of the distribution
    new_y = x * sin(r) + y * cos(r) # change the slope of the distribution
    new_x += shift * cos(r) # parallel shift to the direction of r
    new_y += shift * sin(r) # parallel shift to the direction of r
    return np.concatenate((new_x, new_y), axis=1)

new_xy = sample(x,y,1,6,2)

plt.figure(figsize=(3,3))
plt.scatter(x,y,s=2)
plt.scatter(new_xy[:,0],new_xy[:,1],s=2)
plt.legend(['original','shifted'])
plt.show()
plt.tight_layout()
```

Let's make a circle of 6 gaussian distributions!

```python
n_labels = 6
new_xy = np.empty((0,2))
for i in range(n_labels):
    a = sample(x, y, i+1, n_labels, 6)
    new_xy = np.concatenate((new_xy, a), axis=0)
```

![Figure13.png](https://qiita-image-store.s3.amazonaws.com/0/345318/127a3ac6-898a-f7ac-9a09-896b3f25cdf8.png)

We can also give each distribution a different label

```python
n_labels = 6
plt.figure(figsize=(4.5, 3))
plt.scatter(x, y, s=2, label='original')
for i in range(n_labels):
    x1 = np.random.normal(0, 1, (1000,1)) 
    y1 = np.random.normal(0, 0.3, (1000,1))
    new_xy = sample(x1, y1, i+1, n_labels, 6)
    plt.scatter(new_xy[:,0], new_xy[:,1], 
                s=2, label='label{}'.format(i+1))
plt.legend(bbox_to_anchor=(1.05, 1),
           loc='upper left', borderaxespad=0)
plt.show()
plt.tight_layout()
```

![Figure13.png](https://qiita-image-store.s3.amazonaws.com/0/345318/341c4e0f-3bd8-8c4e-5752-1e4d1a53971e.png)