<jupyter_start><jupyter_text>Memory layout  `shape` and `strides` NumPy array is just a memory block with extra information on how to interpret its contents. Since memory has only linear address space, NumPy arrays need extra information how to lay out this block into multiple dimensions. This is done by means of `shape`  and `strides` attributes:<jupyter_code>import numpy as np
a = np.arange(8, dtype=np.uint8)
a
a.shape, a.strides
b = a.reshape(2, 4)
b
b.shape, b.strides<jupyter_output><empty_output><jupyter_text>![Shape and strides](strides.svg) Note that strides are in bytes:<jupyter_code>a_long = np.arange(8, dtype=np.int32).reshape(2,4)
a_long.strides<jupyter_output><empty_output><jupyter_text>To obtain number of bytes taken by a single element use `itemsize` property:<jupyter_code>a_long.itemsize<jupyter_output><empty_output><jupyter_text>Exercise: TransposeCreate 3x4 random array. Compare the `shape` and `strides` properties of `x` and `x.T`. How can youexplain the new strides?  Exercise: Broadcasting revisitedExplain how broadcasting works internally using the example below. What will be the `shape` and `strides` of `x` and `y` after broadcasting. Test it using `np.broadcast_arrays` in the following example and look at `strides` and `shape` properties of both arrays.```pythonx = np.random.rand(5, 10)y = np.random.rand(10)z = x + yxb, yb = np.broadcast_arrays(x, y)```  Manipulating strides We my use `as_strided` function from NumPy library module  to manipulate the `shape` and `strides` properties (**Warning**: `as_strided` does not check if you remain in the memory bounds of the original array, so use it with care!) For example, we may define overlapping strides:![Overlapping strides](strides2.svg)<jupyter_code>a = np.arange(8, dtype=np.uint8)
a2 = np.lib.stride_tricks.as_strided(a, strides=(2, 1), shape=(3,4))
a2<jupyter_output><empty_output><jupyter_text>Note that in this example some values appear twice, but they do not consume extra memory -- both arrays share the same memory block:<jupyter_code>a[2] = 100
a
a2<jupyter_output><empty_output><jupyter_text>Exercise: Sliding window*Modified Exercise by <NAME> and <NAME>*Use `as_strided` to produce a sliding-window view of a 1D array.```pythondef sliding_window(arr, size=2):    """Produce an array of sliding window views of `arr`        Parameters    ----------    arr : 1D array, shape (N,)        The input array.    size : int, optional        The size of the sliding window.            Returns    -------    arr_slide : 2D array, shape (N - size + 1, size)        The sliding windows of size `size` of `arr`.            Examples    --------    >>> a = np.array([0, 1, 2, 3])    >>> sliding_window(a, 2)    array([[0, 1],           [1, 2],           [2, 3]])    """    return arr   fix this```  Fortran and C-ordering<jupyter_code>c_order = np.arange(6).reshape(2, 3)
c_order
c_order.strides<jupyter_output><empty_output><jupyter_text>Let's see how the array is stored in memory.<jupyter_code>np.ravel(c_order, order='A')<jupyter_output><empty_output><jupyter_text>In C, the last index changes most rapidly as one moves through the array as stored in memory.<jupyter_code>a[0]
fortran_order = np.array(c_order, order='F')
fortran_order
fortran_order.strides
np.ravel(fortran_order, order='A')<jupyter_output><empty_output>
{'fraction_non_alphanumeric': 0.11405356605476978, 'fraction_numerical': 0.01504664459825459, 'mean_word_length': 4.750865051903114, 'pattern_counts': {'":': 0, '<': 35, '<?xml version=': 0, '>': 41, 'https://': 0, 'lorem ipsum': 0, 'www.': 0, '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': '157613', 'license': 'CC-BY-4.0', 'n_tokens_mistral': 1124, 'n_tokens_neox': 1074, 'n_words': 361, 'path': '02 - Memory layout.ipynb', 'repo_name': 'btel/2016-erlangen-euroscipy-advanced-numpy', 'size': '3349'}