## Jupyter Snippet CB2nd 05_array_copies

Jupyter Snippet CB2nd 05_array_copies

# 4.5. Understanding the internals of NumPy to avoid unnecessary array copying

``````import numpy as np
``````
``````def aid(x):
# This function returns the memory
# block address of an array.
return x.__array_interface__['data'][0]
``````
``````a = np.zeros(3)
aid(a), aid(a[1:])
``````
``````(21535472, 21535480)
``````
``````def get_data_base(arr):
"""For a given NumPy array, find the base array
that owns the actual data."""
base = arr
while isinstance(base.base, np.ndarray):
base = base.base
return base

def arrays_share_data(x, y):
return get_data_base(x) is get_data_base(y)
``````
``````print(arrays_share_data(a, a.copy()))
``````
``````False
``````
``````print(arrays_share_data(a, a[:1]))
``````
``````True
``````
``````import numpy as np
a = np.zeros(10)
ax = aid(a)
ax
``````
``````32250112
``````
``````b = a.copy()
aid(b) == ax
``````
``````False
``````
``````a *= 2
aid(a) == ax
``````
``````True
``````
``````c = a * 2
aid(c) == ax
``````
``````False
``````
``````%%timeit a = np.zeros(10000000)
a *= 2
``````
``````4.85 ms ± 24 µs per loop (mean ± std. dev. of 7 runs,
100 loops each)
``````
``````%%timeit a = np.zeros(10000000)
b = a * 2
``````
``````7.7 ms ± 105 µs per loop (mean ± std. dev. of 7 runs,
100 loops each)
``````
``````a = np.zeros((100, 100))
ax = aid(a)
``````
``````b = a.reshape((1, -1))
aid(b) == ax
``````
``````True
``````
``````c = a.T.reshape((1, -1))
aid(c) == ax
``````
``````False
``````
``````%timeit b = a.reshape((1, -1))
``````
``````330 ns ± 0.517 ns per loop (mean ± std. dev. of 7 runs
1000000 loops each)
``````
``````%timeit a.T.reshape((1, -1))
``````
``````5 µs ± 5.68 ns per loop (mean ± std. dev. of 7 runs,
100000 loops each)
``````
``````d = a.flatten()
aid(d) == ax
``````
``````False
``````
``````e = a.ravel()
aid(e) == ax
``````
``````True
``````
``````%timeit a.flatten()
``````
``````2.3 µs ± 18.1 ns per loop (mean ± std. dev. of 7 runs,
100000 loops each)
``````
``````%timeit a.ravel()
``````
``````199 ns ± 5.02 ns per loop (mean ± std. dev. of 7 runs,
10000000 loops each)
``````
``````n = 1000
``````
``````a = np.arange(n)
ac = a[:, np.newaxis]  # column vector
ar = a[np.newaxis, :]  # row vector
``````
``````%timeit np.tile(ac, (1, n)) * np.tile(ar, (n, 1))
``````
``````5.7 ms ± 42.6 µs per loop (mean ± std. dev. of 7 runs,
100 loops each)
``````
``````%timeit ar * ac
``````
``````784 µs ± 2.39 µs per loop (mean ± std. dev. of 7 runs,
1000 loops each)
``````
``````offset = array.strides[0] * i1 + array.strides[1] * i2
``````
``````a = np.random.rand(5000, 5000)
``````
``````%timeit a[0, :].sum()
``````
``````2.91 µs ± 20 ns per loop (mean ± std. dev. of 7 runs,
100000 loops each)
``````
``````%timeit a[:, 0].sum()
``````
``````33.7 µs ± 22.7 ns per loop (mean ± std. dev. of 7 runs
10000 loops each)
``````