<jupyter_start><jupyter_text>Introduction to `numpy` Let's start by running the following cell.<jupyter_code>import numpy as np<jupyter_output><empty_output><jupyter_text>As introduced in the pre-recorded lectures, `numpy` is a fast numerical computation module for Python. The basic tools that `numpy` offers are the *array* data structure and *vectorized* implementations of functions on arrays. In this worksheet, we will assume familiarity with the content of the `numpy` lectures.To recap, a `numpy` array is implemented as a C array: it is a contiguous block of memory that stores data all of the same type. This is in contrast with native Python lists, which are implemented as C arrays that store pointers to their contents, which can be scattered throughout memory. Eliminating this non-locality and the overhead cost of dynamic type checking (which lists must perform even if all their elements are of the same type) leads to a significant edge in speed for `numpy` arrays. This is why we use them.<jupyter_code>a = np.random.rand(1000)
b = np.random.rand(1000)

a_list = list(a)
b_list = list(b)<jupyter_output><empty_output><jupyter_text>In the next cell, write a list comprehension that makes a new list `c_list` whose elements are products of corresponding elements of `a_list` and `b_list`. (Leave the `%%timeit` decorator in the cell; this will let you measure the speed of execution.)<jupyter_code>%%timeit
# write your code here<jupyter_output><empty_output><jupyter_text>Make a new array `c` filled with 1000 zeros. Write a `for` loop that iterates over the elements of arrays `a` and `b` and assigns their product to the corresponding entry of `c`. (The results should convince you that you should always avoid doing this.)<jupyter_code>%%timeit
# write your code here<jupyter_output><empty_output><jupyter_text>Now make `c` again, this time by multiplying the corresponding pairs of elements of `a` and `b` using the `numpy` vectorized multiplication.<jupyter_code>%%timeit
# write your code here<jupyter_output><empty_output><jupyter_text>What do you observe about the performance of each operation? (1 ms = 1000 µs, 1 µs = 1000 ns.) *write your answer here*  §1. Building arrays In the following exercises, build the indicated arrays using `numpy` functions. Don't use lists or loops. Try not to store anything into variables -- you don't need to yet. You can do these in any order. ```array([ 5,  6,  7,  8,  9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21,       22, 23, 24])```<jupyter_code># this is an example
np.arange(5, 25)<jupyter_output><empty_output><jupyter_text>```array([[ 5,  6,  7,  8,  9],       [10, 11, 12, 13, 14],       [15, 16, 17, 18, 19],       [20, 21, 22, 23, 24]])```<jupyter_code># write your code here<jupyter_output><empty_output><jupyter_text>```array([[ 5,  6,  7,  8],       [ 9, 10, 11, 12],       [13, 14, 15, 16],       [17, 18, 19, 20],       [21, 22, 23, 24]])``` ```array([1., 1., 1., 1., 1.])``` ```array([[1., 1.],       [1., 1.],       [1., 1.]])``` ```array([[7., 7.],       [7., 7.],       [7., 7.]])``` ```array([ 1,  4,  7, 10, 13])``` ```array([  1.,   2.,   4.,   8.,  16.,  32.,  64., 128., 256., 512.])``` ```array([ 0.,  2.,  4.,  6.,  8., 10.])``` ```array([20., 15., 10.,  5.,  0.])``` ```array([[[ 0,  1,  2,  3,  4],        [ 5,  6,  7,  8,  9]],       [[10, 11, 12, 13, 14],        [15, 16, 17, 18, 19]],       [[20, 21, 22, 23, 24],        [25, 26, 27, 28, 29]]])``` ```array([False, False, False, False, False, False, False, False,  True,        True,  True,  True,  True,  True,  True,  True,  True,  True,        True,  True])```<jupyter_code># there are 20 entires<jupyter_output><empty_output><jupyter_text>```array([ True, False,  True, False,  True, False,  True, False,  True,       False,  True, False,  True, False,  True, False,  True, False,        True, False])``` ```array([False, False, False, False, False, False, False, False,  True,       False,  True, False,  True, False,  True, False,  True, False,        True, False])``` From this point on it might help to store the arrays to variables. (I suggest just reusing the same variable name; these problems shouldn't depend on each other.) ```array([ 0,  1,  2,  0,  4,  5,  0,  7,  8,  0, 10, 11,  0, 13, 14,  0, 16,       17,  0, 19])``` ```array([ 0,  1,  0,  3,  0,  0,  0,  7,  0,  9,  0, 11,  0, 13,  0,  0,  0,       17,  0, 19])``` ```array([[0, 1, 2, 3],       [4, 5, 6, 0],       [0, 0, 0, 0]])``` ```array([[ 0,  1,  2, 13],       [14, 15, 16, 17],       [18, 19, 10, 11]])``` ```array([[ True, False, False],       [False,  True, False],       [False, False,  True]])```<jupyter_code># hint: use the // operator -- test it to see what it does<jupyter_output><empty_output><jupyter_text>```array([[1., 0., 0., 0., 0.],       [0., 1., 0., 0., 0.],       [0., 0., 1., 0., 0.],       [0., 0., 0., 1., 0.],       [0., 0., 0., 0., 1.]])```<jupyter_code># hint: build two arrays<jupyter_output><empty_output><jupyter_text>§2. Slicing multidimensional arrays Run the next cell first.<jupyter_code>A = np.arange(28).reshape(4, 7)
A<jupyter_output><empty_output><jupyter_text>Obtain the following arrays by slicing `A`. ```array([ 7,  8,  9, 10, 11, 12, 13])``` ```array([ 4, 11, 18, 25])``` ```array([[ 9, 10, 11],       [16, 17, 18],       [23, 24, 25]])``` ```array([[ 1,  2,  3,  4],       [ 8,  9, 10, 11],       [15, 16, 17, 18],       [22, 23, 24, 25]])``` ```array([[ 0,  2,  4,  6],       [ 7,  9, 11, 13],       [14, 16, 18, 20],       [21, 23, 25, 27]])``` ```array([[ 0,  3,  5,  6],       [ 7, 10, 12, 13]])```  §3. Bonus Run the following cell and observe the output.<jupyter_code>A = np.arange(20).reshape(4,5)

print(A, A.sum(), A.sum(0), A.sum(1), sep='\n\n')
v = np.arange(1, 6)
v<jupyter_output><empty_output>
{'fraction_non_alphanumeric': 0.18030801176674166, 'fraction_numerical': 0.07994462709811385, 'mean_word_length': 3.42911877394636, 'pattern_counts': {'":': 0, '<': 49, '<?xml version=': 0, '>': 49, 'https://': 0, 'lorem ipsum': 0, 'www.': 0, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 16, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'chain_length': '12', 'dir': 'jupyter-structured-clean-dedup', 'id': '510945', 'license': 'MIT', 'n_tokens_mistral': 2436, 'n_tokens_neox': 2079, 'n_words': 793, 'path': 'discussion/intro-numpy.ipynb', 'repo_name': 'mm5110/PIC16A', 'size': '5779'}