<jupyter_start><jupyter_text>NumPy PracticeThis notebook offers a set of excercises for different tasks with NumPy.It should be noted there may be more than one different way to answer a question or complete an exercise.Exercises are based off (and directly taken from) the quick introduction to NumPy notebook.Different tasks will be detailed by comments or text.For further reference and resources, it's advised to check out the [NumPy documentation](https://numpy.org/devdocs/user/index.html).And if you get stuck, try searching for a question in the following format: "how to do XYZ with numpy", where XYZ is the function you want to leverage from NumPy.<jupyter_code># Import NumPy as its abbreviation 'np'
import numpy as np
# Create a 1-dimensional NumPy array using np.array()
arr1 = np.array([2, 4, 6, 8, 10])

# Create a 2-dimensional NumPy array using np.array()
arr2 = np.array([[1, 3, 5],
                 [7, 9, 11]])

# Create a 3-dimensional Numpy array using np.array()
arr3 = np.array([[[1, 2, 3],
                  [4, 5, 6],
                  [7, 8, 9]],
                 [[10, 11, 12],
                  [13, 14, 15],
                  [16, 17, 18]]])

arr1, arr2, arr3<jupyter_output><empty_output><jupyter_text>Now we've you've created 3 different arrays, let's find details about them.Find the shape, number of dimensions, data type, size and type of each array.<jupyter_code># Attributes of 1-dimensional array (shape, 
# number of dimensions, data type, size and type)
arr1.shape, arr1.dtype, type(arr1)
# Attributes of 2-dimensional array
arr2.shape, arr2.dtype, type(arr2)
# Attributes of 3-dimensional array
arr3.shape, arr3.dtype, type(arr3)
# Import pandas and create a DataFrame out of one
# of the arrays you've created
import pandas as pd
arr2_df = pd.DataFrame(arr2)
arr2_df
# Create an array of shape (10, 2) with only ones
arr_ones = np.ones((10, 2))
arr_ones
# Create an array of shape (7, 2, 3) of only zeros
arr_zeros = np.zeros((7, 2, 3))
arr_zeros
# Create an array within a range of 0 and 100 with step 3
arr_step3 = np.arange(0, 100, 3)
arr_step3
# Create a random array with numbers between 0 and 10 of size (7, 2)
arr_random_int = np.random.randint(0, 10, (7, 2))
arr_random_int
# Create a random array of floats between 0 & 1 of shape (3, 5)
arr_random_float = np.random.random((3, 5))
arr_random_float
# Set the random seed to 42
np.random.seed(42)

# Create a random array of numbers between 0 & 10 of size (4, 6)
arr_random_int_seeded = np.random.randint(0, 10, (4, 6))
arr_random_int_seeded<jupyter_output><empty_output><jupyter_text>Run the cell above again, what happens?Are the numbers in the array different or the same? Why do think this is?<jupyter_code># Create an array of random numbers between 1 & 10 of size (3, 7)
# and save it to a variable
arr_random_numbers = np.random.randint(1, 10, (4, 6))

# Find the unique numbers in the array you just created
arr_random_numbers, np.unique(arr_random_numbers)
# Find the 0'th index of the latest array you created
arr_random_numbers[0]
# Get the first 2 rows of latest array you created
arr_random_numbers[:2]
# Get the first 2 values of the first 2 rows of the latest array
arr_random_numbers[:2, :2]
# Create a random array of numbers between 0 & 10 and an array of ones
# both of size (3, 5), save them both to variables
arr_random_numbers1 = np.random.randint(0, 10, (3, 5))
arr_ones1 = np.ones((3, 5))

arr_random_numbers1, arr_ones1
# Add the two arrays together
arr_random_numbers1 + arr_ones1
# Create another array of ones of shape (5, 3)
arr_ones2 = np.ones((5, 3))
arr_ones2
# Try add the array of ones and the other most recent array together
arr_random_numbers1 + arr_ones2.T<jupyter_output><empty_output><jupyter_text>When you try the last cell, it produces an error. Why do think this is?How would you fix it?<jupyter_code># Create another array of ones of shape (3, 5)
arr_ones3 = np.ones((3, 5))
arr_ones3
# Subtract the new array of ones from the other most recent array
arr_random_numbers1 - arr_ones3
# Multiply the ones array with the latest array
arr_random_numbers1 * arr_ones3
# Take the latest array to the power of 2 using '**'
arr_random_numbers1 ** 2
# Do the same thing with np.square()
np.square(arr_random_numbers1)
# Find the mean of the latest array using np.mean()
np.mean(arr_random_numbers1)
# Find the maximum of the latest array using np.max()
np.max(arr_random_numbers1)
# Find the minimum of the latest array using np.min()
np.min(arr_random_numbers1)
# Find the standard deviation of the latest array
np.std(arr_random_numbers1)
# Find the variance of the latest array
np.var(arr_random_numbers1)
# Reshape the latest array to (3, 5, 1)
arr_random_numbers1_reshaped = arr_random_numbers1.reshape((3, 5, 1))
arr_random_numbers1, arr_random_numbers1_reshaped
# Transpose the latest array
arr_random_numbers1_reshaped.T<jupyter_output><empty_output><jupyter_text>What does the transpose do?<jupyter_code># Create two arrays of random integers between 0 to 10
# one of size (3, 3) the other of size (3, 2)
arr_random_numbers2 = np.random.randint(0, 10, (3, 3))
arr_random_numbers3 = np.random.randint(0, 10, (3, 2))
arr_random_numbers2, arr_random_numbers3
# Perform a dot product on the two newest arrays you created
np.dot(arr_random_numbers2, arr_random_numbers3)
# Create two arrays of random integers between 0 to 10
# both of size (4, 3)
arr_random_numbers4 = np.random.randint(0, 10, (4, 3))
arr_random_numbers5 = np.random.randint(0, 10, (4, 3))
arr_random_numbers4, arr_random_numbers5
# Perform a dot product on the two newest arrays you created
np.dot(arr_random_numbers4, arr_random_numbers5.T)<jupyter_output><empty_output><jupyter_text>It doesn't work. How would you fix it?<jupyter_code># Take the latest two arrays, perform a transpose on one of them and then perform 
# a dot product on them both
np.dot(arr_random_numbers4, arr_random_numbers5.T)<jupyter_output><empty_output><jupyter_text>Notice how performing a transpose allows the dot product to happen.Why is this?Checking out the documentation on [`np.dot()`](https://docs.scipy.org/doc/numpy/reference/generated/numpy.dot.html) may help, as well as reading [Math is Fun's guide on the dot product](https://www.mathsisfun.com/algebra/vectors-dot-product.html).Let's now compare arrays.<jupyter_code># Create two arrays of random integers between 0 & 10 of the same shape
# and save them to variables
arr_random_numbers6 = np.random.randint(0, 10, (10, 5))
arr_random_numbers7 = np.random.randint(0, 10, (10, 5))
arr_random_numbers6, arr_random_numbers7
# Compare the two arrays with '>'
arr_random_numbers6 > arr_random_numbers7<jupyter_output><empty_output><jupyter_text>What happens when you compare the arrays with `>`?<jupyter_code># Compare the two arrays with '>='
arr_random_numbers6 >= arr_random_numbers7
# Find which elements of the first array are greater than 7
arr_random_numbers6 > 7
# Which parts of each array are equal? (try using '==')
arr_random_numbers6 == arr_random_numbers7
# Sort one of the arrays you just created in ascending order
np.sort(arr_random_numbers6)
# Sort the indexes of one of the arrays you just created
np.argsort(arr_random_numbers6)
# Find the index with the maximum value in one of the arrays you've created
np.argmax(arr_random_numbers6)
# Find the index with the minimum value in one of the arrays you've created
np.argmin(arr_random_numbers7)
# Find the indexes with the maximum values down the verticial axis
# of one of the arrays you created
np.argmax(arr_random_numbers6, axis=1)
# Find the indexes with the minimum values across the horizontal axis
# of one of the arrays you created
np.argmin(arr_random_numbers7, axis=1)
# Create an array of normally distributed random numbers
np.random.randn(3, 5)
# Create an array with 10 evenly spaced numbers between 1 and 100
np.linspace(1, 100, 10)<jupyter_output><empty_output>
{'fraction_non_alphanumeric': 0.08555133079847908, 'fraction_numerical': 0.036628643852978454, 'mean_word_length': 4.942018072289157, 'pattern_counts': {'":': 0, '<': 33, '<?xml version=': 0, '>': 39, 'https://': 3, 'lorem ipsum': 0, 'www.': 1, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 0, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'chain_length': '8', 'dir': 'jupyter-structured-clean-dedup', 'id': '331357', 'license': 'MIT', 'n_tokens_mistral': 2763, 'n_tokens_neox': 2517, 'n_words': 999, 'path': 'section 0 - practice/numpy-exercises.ipynb', 'repo_name': 'evnrodr/machine-learning-course', 'size': '7890'}