Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Empty file.
20 changes: 20 additions & 0 deletions Numpy/Array Basics/Random Shuffle/task-info.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
type: edu
files:
- name: task.py
visible: true
placeholders:
- offset: 87
length: 16
placeholder_text: '# TODO: shuffle rows of `arr` in place'
- offset: 118
length: 28
placeholder_text: '# TODO: now permute the elements within rows of `arr`'
- offset: 162
length: 45
placeholder_text: '# TODO: fully randomize the array'
- name: tests/test_task.py
visible: false
- name: __init__.py
visible: false
- name: tests/__init__.py
visible: false
92 changes: 92 additions & 0 deletions Numpy/Array Basics/Random Shuffle/task.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,92 @@
## Random Shuffle

Sometimes you need to shuffle the contents of an array. For instance, in machine learning tasks
it is common to shuffle data and normalize it.

NumPy offers two methods that will provide you with randomly shuffled (or **permuted**) data:
- [`random.Generator.permutation`](https://numpy.org/doc/stable/reference/random/generated/numpy.random.Generator.permutation.html#numpy.random.Generator.permutation): randomly permutes a sequence, or return a permuted range.
- [`random.Generator.shuffle`](https://numpy.org/doc/stable/reference/random/generated/numpy.random.Generator.shuffle.html#numpy.random.Generator.shuffle): modifies an array or sequence **in-place** by shuffling its contents.

The key difference between these two methods is that `permutation` returns an array, while
`shuffle` modifies it in-place. Additionally, `permutation` allows you to create a permuted sequence from
range. For arrays with more than one dimension, the order of sub-arrays is changed but their contents remains the same.
Please check out the examples below.

1. Shuffle / permute a sequence
```python
rng = np.random.default_rng()
print(rng.permutation(10)) # permutation returns a permuted range
```
Output (will be different every time):
```text
[6 5 0 4 9 1 8 2 3 7]
```

```python
arr = np.arange(10)
rng.shuffle(arr) # Shuffle sequence in place
print(arr)
```
Output:
```text
[0 3 5 7 8 6 9 1 2 4]
```
2. Shuffle / permute a 2D array
```python
arr = np.arange(9).reshape((3, 3))
print(rng.permutation(arr)) # permutation returns a permuted array, order within rows is maintained
```
Output:
```text
[[3 4 5]
[6 7 8]
[0 1 2]]
```
```python
arr = np.arange(9).reshape((3, 3))
rng.shuffle(arr) # Shuffle array in place, order within rows is maintained
print(arr)
```
Output:
```text
[[6 7 8]
[3 4 5]
[0 1 2]]
```
2. Shuffle / permute a 2D array along another axis
```python
arr = np.arange(9).reshape((3, 3))
print(rng.permutation(arr, axis=1)) # permutation returns an array permuted within rows
```
Output:
```text
[[2 0 1]
[5 3 4]
[8 6 7]]
```
```python
arr = np.arange(9).reshape((3, 3))
rng.shuffle(arr, axis=1) # Shuffle array in place within rows
print(arr)
```
Output:
```text
[[0 2 1]
[3 5 4]
[6 8 7]]
```

### Task

First, `shuffle` the rows of the array `arr` (0th axis is the default axis).
Then, randomly permute the numbers within rows in `arr` and assign the result to
the variable `permuted_2d`.
Still, your array is not fully random, since all the elements remain in the same rows
where they started. Create a `fully_random` array. Use some of the methods we
learned earlier.

<div class="hint">Use the examples in task description to shuffle and permute the array.</div>

<div class="hint">To fully randomize it, you could first, <code>flatten</code> the array, apply the <code>permutation</code>
method to it, and <code>reshape</code> back to the original shape. All these things can be done in one
line of code.</div>
17 changes: 17 additions & 0 deletions Numpy/Array Basics/Random Shuffle/task.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
import numpy as np

rng = np.random.default_rng()

arr = np.arange(100).reshape(5, 20)
rng.shuffle(arr)
permuted_2d = rng.permutation(arr, axis=1)
fully_random = rng.permutation(arr.flatten()).reshape(5, 20)


if __name__ == '__main__':
print(arr)
for i in arr:
print(i[0], min(i))
print(i[-1], max(i))
print(permuted_2d)
print(fully_random)
Empty file.
28 changes: 28 additions & 0 deletions Numpy/Array Basics/Random Shuffle/tests/test_task.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,28 @@
import unittest
import numpy as np

from task import arr, permuted_2d, fully_random


class TestCase(unittest.TestCase):
def test_shape(self):
self.assertEqual(arr.shape, (5, 20), msg="wrong shape of the array 'arr'")
self.assertEqual(permuted_2d.shape, (5, 20), msg="wrong shape of the array 'permuted_2d'")
self.assertEqual(fully_random.shape, (5, 20), msg="wrong shape of the array 'fully_random'")

def test_arr(self):
for i in arr:
# This test checks if in each row the minimum element goes first and maximum - last.
self.assertTrue(i[0] == min(i) and i[-1] == max(i), msg="'arr' should be shuffled along the 0th axis")

def test_two_d(self):
for i in permuted_2d:
# This test checks that differences between all neighboring elements in rows of the array
# are not equal to 1 (in non-shuffled rows they would be).
self.assertFalse(all([(x - i[i.tolist().index(x) - 1]) == 1 for x in i if i.tolist().index(x) > 0]),
msg="'permuted_2d' should be shuffled along the 1st axis")

def test_random(self):
# This test checks if elements were also randomized between the rows.
for i in fully_random:
self.assertTrue(max(i) - min(i) > 19, "'fully_random' needs to be fully shuffled!")
1 change: 1 addition & 0 deletions Numpy/Array Basics/lesson-info.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -5,3 +5,4 @@ content:
- Create an Array from Range
- Reshape
- Random Sampling
- Random Shuffle