<jupyter_start><jupyter_text>100 Numpy Exercises[numpy-100](https://github.com/rougier/numpy-100)中文版及一些注解。  1. 导入Numpy<jupyter_code>import numpy as np<jupyter_output><empty_output><jupyter_text>2. 打印Numpy版本号及其配置<jupyter_code>np.__version__
np.show_config()<jupyter_output>mkl_info:
    libraries = ['mkl_rt', 'pthread']
    library_dirs = ['/home/shensir/anaconda3/lib']
    define_macros = [('SCIPY_MKL_H', None), ('HAVE_CBLAS', None)]
    include_dirs = ['/home/shensir/anaconda3/include']
blas_mkl_info:
    libraries = ['mkl_rt', 'pthread']
    library_dirs = ['/home/shensir/anaconda3/lib']
    define_macros = [('SCIPY_MKL_H', None), ('HAVE_CBLAS', None)]
    include_dirs = ['/home/shensir/anaconda3/include']
blas_opt_info:
    libraries = ['mkl_rt', 'pthread']
    library_dirs = ['/home/shensir/anaconda3/lib']
    define_macros = [('SCIPY_MKL_H', None), ('HAVE_CBLAS', None)]
    include_dirs = ['/home/shensir/anaconda3/include']
lapack_mkl_info:
    libraries = ['mkl_rt', 'pthread']
    library_dirs = ['/home/shensir/anaconda3/lib']
    define_macros = [('SCIPY_MKL_H', None), ('HAVE_CBLAS', None)]
    include_dirs = ['/home/shensir/anaconda3/include']
lapack_opt_info:
    libraries = ['mkl_rt', 'pthread']
    library_dirs = ['/home/shensir/anaconda3/lib[...]<jupyter_text>3. 创建一个长度(size)为10的向量(vector)注意这里就是创建一个`np.ndarray`<jupyter_code>z = np.zeros(10)
z<jupyter_output><empty_output><jupyter_text>4. 计算数组的内存大小<jupyter_code>z = np.zeros((10, 10))
print("%d bytes" % (z.size * z.itemsize))<jupyter_output>800 bytes<jupyter_text>注意这里就是简单的把总元素个数`z.size`（100）， 乘上单个元素所占的内存`z.itemsize`(8 bytes).  5. 在命令行打印出Numpy中add函数的帮助文档信息 这里主要是有关命令行调用Python的问题，我们可以在命令行从`python --help`开始， 找到`python -c`符合我们的要求，所以这里只需要在命令行执行`python -c "import numpy; numpy.info(numpy.add)"`即可。就等同于在Python解释器中执行如下程序：```pythonimport numpynumpy.info(numpy.add)``` 此外，针对Numpy,我们可以有很多种方式查看文档:上面的`np.info(np.add)`, 以及利用help的`help(np.add)`, 和比较少用的doc方法的调用`print(np.add.__doc__)`（输出和`np.info`一致）, 一般来说用`np.info`就可以了，也比较方便。如果使用`IPython`的话，可以直接`np.add?`回车  6. 创建一个长度为10的向量，其第五个值为1， 其他为0<jupyter_code>z = np.zeros(10)
z[4] = 1
z<jupyter_output><empty_output><jupyter_text>7. 创建一个包含从10到49所有整数的向量<jupyter_code>z = np.arange(10, 50)
z<jupyter_output><empty_output><jupyter_text>注意Python也有内建函数`range`具有相似的功能，相对而言，Numpy的`arange`由于使用了内存优化技术，其效率要高很多。我们可以做个简单的水平对比。例子来自*Scipy Lecture Notes*<jupyter_code>%timeit [i**2 for i in range(1000)]
%timeit a = np.arange(1000) ** 2<jupyter_output>5.13 µs ± 842 ns per loop (mean ± std. dev. of 7 runs, 100000 loops each)<jupyter_text>8. 反转一个向量（逆序）<jupyter_code>z = np.arange(10)
z
z = z[::-1]
z<jupyter_output><empty_output><jupyter_text>9. 创建一个3x3的矩阵， 包含数字0到8<jupyter_code>z = np.arange(0, 9).reshape(3, 3)
z<jupyter_output><empty_output><jupyter_text>这里可以在原题目的基础上进行拓展，上面的实现中0到8是可以看作以行为顺序，如我我们希望0到8以列为顺序排列呢？<jupyter_code># 列为顺序
z = np.arange(0, 9).reshape(3, 3).T
z<jupyter_output><empty_output><jupyter_text>其实只需要把原来的矩阵转置就可以了:-)  10. 找出[1,2,0,0,4,0] 中非0数字的位置<jupyter_code>z = np.array([1,2,0,0,4,0])
z.nonzero()<jupyter_output><empty_output><jupyter_text>11. 创建3x3的单位矩阵<jupyter_code>z = np.eye(3)
z<jupyter_output><empty_output><jupyter_text>12. 创建3x3x3数组，以随机数字填充<jupyter_code>z = np.random.random((3, 3, 3))
z<jupyter_output><empty_output><jupyter_text>13. 创建10x10数组，以随机数字填充，并找出其中的最大值和最小值<jupyter_code>z = np.random.random((10, 10))
z
z.max(), z.min()<jupyter_output><empty_output><jupyter_text>14. 创建长度为10的随机向量，并计算其均值<jupyter_code>z = np.random.random((10))
z
z.mean()<jupyter_output><empty_output><jupyter_text>15. 创建一个二维数组，其边界值为1，内部值为0<jupyter_code>z = np.ones((5, 5))
z[1:-1, 1:-1] = 0
z<jupyter_output><empty_output><jupyter_text>16. 将现有的数组（nxn）用0组成的边界包裹<jupyter_code>z = np.ones((5, 5))
z
m = np.pad(z, (1, 1), mode='constant', constant_values=0)
m<jupyter_output><empty_output><jupyter_text>17. 下列表达式的结果是什么```python0 * np.nannp.nan == np.nannp.inf > np.nannp.nan - np.nannp.nan in set([np.nan])0.3 == 3 * 0.1```<jupyter_code>0 * np.nan<jupyter_output><empty_output><jupyter_text>有`np.nan`参与的算术操作返回均为`np.nan`<jupyter_code>np.nan == np.nan<jupyter_output><empty_output><jupyter_text>这里是合理的，比如我们从数据集读出两列数据全部是`np.nan`， 如果上面的表达式设计为返回`True`， 那么我们在完全不知道两列数据的情况下就判定二者是相等的，这显然是不合理的。所以这里返回的是`False`.<jupyter_code>np.inf > np.nan<jupyter_output><empty_output><jupyter_text>同样地，我们不能比较无穷大与缺失值的大小<jupyter_code>np.nan in set([np.nan])
0.3 == 3 * 0.1<jupyter_output><empty_output><jupyter_text>由于浮点数（`float`）运算存在误差，我们不能直接比较其大小。Numpy为我们提供了`np.allclose`函数来比较浮点数之间的近似相等。此外，此函数还支持`np.ndarray`的比较。<jupyter_code>np.allclose(0.3, 3 * 0.1)<jupyter_output><empty_output><jupyter_text>18. 创建一个5x5的矩阵，其中1，2，3，4正好在矩阵对角线元素下方<jupyter_code>z = np.diag(np.arange(1, 5), k=-1)
z<jupyter_output><empty_output><jupyter_text>19. 创建一个8x8的矩阵，并用0，1标记为国际象棋棋盘的形式如下所示, 黑色部分标记为1.<jupyter_code>z = np.zeros((8, 8))
z[1::2, ::2] = 1  # 第2, 4, 6, 8行填充
z[::2, 1::2] = 1  # 第1， 3， 5， 7行填充
z<jupyter_output><empty_output><jupyter_text>20. 现有维度为6x7x8的数组，找出其中第100个元素的索引(x, y, z)<jupyter_code>print(np.unravel_index(99, (6, 7, 8)))<jupyter_output>(1, 5, 3)<jupyter_text>上面的是给出的答案，一开始我并不知道这个函数，采用了下面的方法，可以作为参考。<jupyter_code>z = np.arange(6*7*8).reshape(6, 7, 8)
np.where(z == 99)<jupyter_output><empty_output><jupyter_text>这是通过Numpy找出来具体位置，但是具体计算的方法并未给出，这里简单解释下。首先，我们可以形象第考虑“数组的维度越往后，对应数据的颗粒度越小”，也就是说，在上面的例子中，我们可以认为6x7x8的立方体是通过如下的方法来构建的：先将所有的一列值(6 * 7 * 8)排成一行，之后每8个组成一个“长条”， 这样就有6*7个长条；之后将每7个长条，上下拼接，铺成一个平面；这样我们就有6个平面，将这6个平面堆起来，就得到了我们最终的“立方体”。那么第100个元素又在哪里呢？为方便起见，我们从“颗粒度”大的开始，依次定位其位置。首先，可以知道每一层含有7*8=56个元素，所以由`100 // 56 = 1`得其位于第二层， 对应到该维度得到索引就是1，即返回的`array[1]`。之后在第二层中继续定位， 去除第一层的56个元素，这里还剩下44个。又由于平面为7x8的，所以由`44 // 8 = 5`得其位于第6行，对应该维度的索引是5， 即返回的`array[5]`, 最后剩下4个元素在新的一行，对应维度的索引为3， 即返回的`array[3]`.由此得到最终的索引为（1， 5， 3）  21. 用`tile`函数创建一个8x8的棋盘<jupyter_code>unit = np.array([[0, 1], [1, 0]])
z = np.tile(unit, (4, 4))
z<jupyter_output><empty_output><jupyter_text>`tile`的原意就是铺瓷砖，是其作用的一个形象的比喻，这里我们把8x8的棋盘划分为4x4=16块“瓷砖”（这里的`unit`）， 之后将其平铺在一起即可。  22. 标准化一个5x5的随机矩阵<jupyter_code>z = np.random.random((5, 5))
z = (z - z.mean()) / z.std()
z<jupyter_output><empty_output><jupyter_text>23. 创建一个自定义的包含四个无符号字节（RGBA）的`dtype`来描述颜色<jupyter_code>color = np.dtype([("r", np.ubyte, 1),
                  ("g", np.ubyte, 1),
                  ("b", np.ubyte, 1),
                  ("a", np.ubyte, 1)])
color<jupyter_output><empty_output><jupyter_text>24. 5x3的矩阵与3x2的矩阵相乘<jupyter_code>z = np.dot(np.ones((5, 3)), np.ones((3, 2)))
z
# 也可以使用操作符 @
z = np.ones((5, 3)) @ np.ones((3, 2))
z<jupyter_output><empty_output><jupyter_text>25. 给定一个一维数组，将值在3和8之间的数字变为其负数<jupyter_code>z = np.arange(10)
z[(z > 3) & (z < 8)] *= -1
z<jupyter_output><empty_output><jupyter_text>26. 下面脚本的输出是什么```python Author: <NAME>print(sum(range(5),-1))from numpy import *print(sum(range(5),-1))```<jupyter_code>sum(range(5), -1)<jupyter_output><empty_output><jupyter_text>这里是使用Python内置的`sum`函数, 它把所有的参数都当作求和的一部分相加， 这里就是简单地将所有的数字相加，10 - 1 = 9<jupyter_code>np.sum(range(5), -1)<jupyter_output><empty_output><jupyter_text>这里使用的是Numpy中的`np.sum`， 这里的`-1`并非待加的数字，而是另外一个参数的值，代表多维数组在求和时各个轴求和的顺序。具体可以`help(np.sum)`  27. `z`是整数组成的向量，判断下列表达式是否正确<jupyter_code>z = np.arange(10)
z
# 1
z ** z<jupyter_output><empty_output><jupyter_text>前面提到过， 对于数组之间的`**`等算术运算， 是元素一一对应进行运算的(element-wise), 如这里387420489，就等于9**9<jupyter_code># 2
2 << z >> 2<jupyter_output><empty_output><jupyter_text>本质上进行两次移位运算，也就是等于`(2 > 2`.下面将其拆开来看。<jupyter_code>2 << z<jupyter_output><empty_output><jupyter_text>就是将2分别左移0， 1， 2， ...， 9位，得到的就是`2 << 0, 2<<1, ..., 2<<9`,如下所示：<jupyter_code>part1 = [2 << i for i in range(10)]
part1<jupyter_output><empty_output><jupyter_text>可以看到与`2 << z`的输出是一致的。之后就是进行右移位操作，不同之处在于，这里是对于数组`2 << z`中的每个元素进行右移位，分别右移2个位置。每个数值右移2代表对每个值`x`，取`x // 4`, 对`part1`继续处理<jupyter_code>[i // 4 for i in part1]<jupyter_output><empty_output><jupyter_text>可以看到其与`2 > 2`的输出是一致的。<jupyter_code># 3
z <- z<jupyter_output><empty_output><jupyter_text>这里涉及的主要是优先级的问题，随便找个操作符，如`<`,通过`help("<")`即可查看所有操作符的优先级，默认是从低优先级到高优先级。可以看到，`-1`相比`<`具有更高的优先级， 所以这里就等同于`z < (-z)`，测试如下<jupyter_code>z < (-z)
# 4
1j * z<jupyter_output><empty_output><jupyter_text>对复数的运算的支持<jupyter_code># 5
z/1/1<jupyter_output><empty_output><jupyter_text>也就是`(z/1)/1`<jupyter_code># 6
z < z > z<jupyter_output><empty_output><jupyter_text>这里参考了下Python表达式的[文档](https://docs.python.org/2/reference/expressions.htmlnot-in),和[stackoverflow](https://stackoverflow.com/questions/18755059/is-abc-valid-python)找到>Formally, if `a, b, c, …, y, z` are expressions and `op1, op2, …, opN` are comparison operators, then a `op1 b op2 c ... y opN z` is equivalent to `a op1 b and b op2 c and ... y opN z`, except that each expression is evaluated at most once.就是说，在一个表达式里面进行连续比较的时候，如`x < y <= z`,首先是符合语法的，其等同于`x < y adn y <=z`, 只不过对于重复的元素（这里的`y`）只估计一次。所以我们在Python原生的`list`中进行上述`z`的运算是可以正常返回的，代码如下。<jupyter_code>l1 = [1, 2]
l1 < l1 > l1
(l1 < l1) and (l1 > l1)<jupyter_output><empty_output><jupyter_text>因为`l1  l1`全部是`False`,所以其`and`也是`False`.但是对于我们的`z`，也就是`np.ndarray`类型的数据，情况就有所不同。这里`z  z`依旧是估计为`z  z`, 其中`z  z`都是可以正常返回的，且结果都是一个长度为`z.size()`的`array`， 元素全部是布尔值。<jupyter_code>z < z
z > z<jupyter_output><empty_output><jupyter_text>不可行的是两者之间的`and`。 因为在进行`and`操作时，Numpy无法确切地知道形如`array([False, False, ...])`的数组到底是估计为`False`，还是`True`， 因为这里有两种方法来定义一个数组的布尔值：其一是`ａｌｌ`，即所有的元素全是`Ｔｒｕｅ`才判定为`Ｔｒｕｅ`，否则为`Ｆａｌｓｅ`；　另外一种方法是`ａｎｙ`，　即只要数组中有一个`Ｔｒｕｅ`，我们就判定其为`Ｔｒｕｅ`, 否则判定为`Ｆａｌｓｅ`. 正是这种不确定性使得Numpy报错，并建议使用`any`或者`all`.  28. 下列表达式的结果是什么```pythonnp.array(0) / np.array(0)np.array(0) // np.array(0)np.array([np.nan]).astype(int).astype(float)```<jupyter_code>np.array(0) / np.array(0)<jupyter_output>/home/shensir/anaconda3/lib/python3.6/site-packages/ipykernel_launcher.py:1: RuntimeWarning: invalid value encountered in true_divide
  """Entry point for launching an IPython kernel.<jupyter_text>返回`nan`并带有警告说在进行真除(true_divide)的时候出现问题，即0做分母。<jupyter_code>np.array(0) // np.array(0)<jupyter_output>/home/shensir/anaconda3/lib/python3.6/site-packages/ipykernel_launcher.py:1: RuntimeWarning: divide by zero encountered in floor_divide
  """Entry point for launching an IPython kernel.<jupyter_text>返回0, 并带有警告说在进行地板除(floor_divide)的时候出现问题，即0做分母。<jupyter_code>np.array([np.nan]).astype(int).astype(float)<jupyter_output><empty_output><jupyter_text>29. 舍入浮点数数组，使其尽可能远离0即-0.3， -0.5， -0.6等近似为-1，而非0； 0.3， 0.5， 0.6等近似为1，而非0.<jupyter_code>z = np.random.uniform(-10, 10, 10)
z
np.copysign(np.ceil(np.abs(z)), z)<jupyter_output><empty_output><jupyter_text>30. 找到两个数组中相同的元素 我们首先考虑内置的函数，但是我们不知道是否有类似的函数，所以我们可以灵活使用`np.lookfor`来找出我们要的函数。<jupyter_code>np.lookfor("common values")<jupyter_output>Search results for 'common values'
----------------------------------
numpy.ma.intersect1d
    Returns the unique elements common to both arrays.
numpy.gcd
    Returns the greatest common divisor of ``|x1|`` and ``|x2|``
numpy.lcm
    Returns the lowest common multiple of ``|x1|`` and ``|x2|``
numpy.intersect1d
    Find the intersection of two arrays.
numpy.ma.common_fill_value
    Return the common filling value of two masked arrays, if any.
numpy.add
    Add arguments element-wise.
numpy.less
    Return the truth value of (x1 < x2) element-wise.
numpy.sign
    Returns an element-wise indication of the sign of a number.
numpy.sqrt
    Return the non-negative square-root of an array, element-wise.
numpy.choose
    Construct an array from an index array and a set of arrays to choose from.
numpy.einsum
    einsum(subscripts, *operands, out=None, dtype=None, order='K',
numpy.nditer
    Efficient multi-dimensional iterator object to iterate over arrays.
numpy.greater
    Return the truth v[...]<jupyter_text>我们发现返回得到第一个函数`np.intersect1d`就是我们要找的，进一步查看其用法。<jupyter_code>np.info(np.intersect1d)<jupyter_output>intersect1d(ar1, ar2, assume_unique=False, return_indices=False)

Find the intersection of two arrays.

Return the sorted, unique values that are in both of the input arrays.

Parameters
----------
ar1, ar2 : array_like
    Input arrays. Will be flattened if not already 1D.
assume_unique : bool
    If True, the input arrays are both assumed to be unique, which
    can speed up the calculation.  Default is False.
return_indices : bool
    If True, the indices which correspond to the intersection of the two
    arrays are returned. The first instance of a value is used if there are
    multiple. Default is False.

    .. versionadded:: 1.15.0

Returns
-------
intersect1d : ndarray
    Sorted 1D array of common and unique elements.
comm1 : ndarray
    The indices of the first occurrences of the common values in `ar1`.
    Only provided if `return_indices` is True.
comm2 : ndarray
    The indices of the first occurrences of the common values in `ar2`.
    Only provided if `return_indices`[...]<jupyter_text>根据文档就可以直接使用了。<jupyter_code>z1 = np.arange(-5, 5)
z2 = np.arange(10)
np.intersect1d(z1, z2)<jupyter_output><empty_output><jupyter_text>31. 如何忽视所有Numpy的警告（不推荐）<jupyter_code># 自杀模式启动:-)
defaults = np.seterr(all="ignore")
Z = np.ones(1) / 0
# 恢复理智
_ = np.seterr(**defaults)
# 也可以定义错误处理的细节
with np.errstate(divide='warn'):
    Z = np.ones(1) / 0<jupyter_output>/home/shensir/anaconda3/lib/python3.6/site-packages/ipykernel_launcher.py:3: RuntimeWarning: divide by zero encountered in true_divide
  This is separate from the ipykernel package so we can avoid doing imports until<jupyter_text>32. 下面的表达式会返回`True`吗```pythonnp.sqrt(-1) == np.emath.sqrt(-1)```<jupyter_code>np.sqrt(-1) == np.emath.sqrt(-1)
np.sqrt(-1), np.emath.sqrt(-1)<jupyter_output><empty_output><jupyter_text>33. 如何获取昨天，今天，明天的日期<jupyter_code>yesterday = np.datetime64('today', 'D') - np.timedelta64(1, 'D')
today     = np.datetime64('today', 'D')
tomorrow  = np.datetime64('today', 'D') + np.timedelta64(1, 'D')
yesterday, today, tomorrow<jupyter_output><empty_output><jupyter_text>34. 如何获取2016年7月全部31天的日期<jupyter_code>z = np.arange('2016-07', '2016-08', dtype='datetime64[D]')
z<jupyter_output><empty_output><jupyter_text>35. 如何以替换的方式（in place）计算$((A+B)*(-A/2))$（不通过复制）<jupyter_code>A = np.ones(3)*1
B = np.ones(3)*2
C = np.ones(3)*3
np.add(A,B,out=B)
np.divide(A,2,out=A)
np.negative(A,out=A)
np.multiply(A,B,out=A)<jupyter_output><empty_output><jupyter_text>36. 用5种方法提取随机数组中的整数部分<jupyter_code>z = np.random.uniform(0, 10, 10)
z
# 1
z - z % 1
# 2
np.floor(z)
# 3
np.ceil(z) - 1
# 4
z.astype(int)
# 5
np.trunc(z)<jupyter_output><empty_output><jupyter_text>37. 创建一个5x5的矩阵，每行均为0到4<jupyter_code># 1,答案的方法
z = np.zeros((5, 5))
z += np.arange(5)
z
# 2,利用tile
z = np.tile(np.arange(5), (5, 1))
z<jupyter_output><empty_output><jupyter_text>38. 现有一个可以生成10个整数的生成器函数，利用其建立一个数组<jupyter_code># 1, 答案的方法
def gen():
    for i in range(10):
        yield i
        
z = np.fromiter(gen(), dtype=float, count=-1)
z
# 2, 列表解析
z = np.array([i for i in gen()])
z<jupyter_output><empty_output><jupyter_text>39. 创建一个长度为10，范围从0到1的向量（不包括0，1）<jupyter_code>z = np.linspace(0, 1, 11, endpoint=False)[1:]
z<jupyter_output><empty_output><jupyter_text>40. 创建一个长度为10的随机数组并排序<jupyter_code>z = np.random.random(10)
z
z.sort()
z<jupyter_output><empty_output><jupyter_text>41. 对于长度较小的数组，如何更高效地求和（相对`np.sum`）<jupyter_code>z = np.arange(10)
np.add.reduce(z)
%timeit np.add.reduce(z)
%timeit np.sum(z)<jupyter_output>3.94 µs ± 299 ns per loop (mean ± std. dev. of 7 runs, 100000 loops each)<jupyter_text>可以看到`np.add.reduce`此时差不多快上一倍  42. 检查两个数组A， B是否相等<jupyter_code>A = np.random.randint(0,2,5)
B = np.random.randint(0,2,5)
# 1， 已知A，B的shape相等
# 存在容错，适用于浮点数的比较
np.allclose(A, B)
# 2. 同时检查shape与数值
# 要求数值完全相等
np.array_equal(A, B)<jupyter_output><empty_output><jupyter_text>43. 限制数组为不可变数组（read only）<jupyter_code>z = np.zeros(10)
z.flags
z.flags.writeable = False
z.flags
z[0] = 1<jupyter_output><empty_output><jupyter_text>44. 给定10x2矩阵代表平面座标系中座标，将其转化为极座标系座标<jupyter_code>z = np.random.random((10, 2))
x, y = z[:, 0], z[:, 1]
r = np.sqrt(x**2 + y**2)
theta = np.arctan2(y, x)
r, theta<jupyter_output><empty_output><jupyter_text>45. 创建一个长度为10的随机向量，并将其中最大的数改为0<jupyter_code>z = np.random.random(10)
z
z[z.argmax()] = 0
z<jupyter_output><empty_output><jupyter_text>46. 创建一个结构化的数组，其元素为x轴，y轴的座标，并覆盖[0,1]x[0, 1]<jupyter_code>z = np.zeros((5, 5), [('x', float), ('y', float)])
z = np.meshgrid(np.linspace(0, 1, 5),
                np.linspace(0, 1, 5))
z<jupyter_output><empty_output><jupyter_text>47. 给定两个数组X，Y， 计算其柯西矩阵C(Cauchy Matrix)并求其行列式$$C_{ij} = \frac{1}{x_i-y_j}$$<jupyter_code>x = np.arange(8)
y = x + 0.5
C = np.subtract.outer(x, y)
C
np.linalg.det(C)<jupyter_output><empty_output><jupyter_text>其实这里`np.subtract.outer`就等于进行了broadcast,我们也可以像下面这样写。<jupyter_code>C_test = x.reshape(8, 1)- y.reshape(1, 8)
C_test
np.linalg.det(C_test)
# 测试两种方法返回的C是否相同
np.array_equal(C, C_test)<jupyter_output><empty_output><jupyter_text>48. 打印Numpy所有标量类型(scalar type)可表示的最值<jupyter_code>for dtype in [np.int8, np.int16, np.int32, np.int64]:
    info = np.iinfo(dtype)
    print(f"{dtype}: min={info.min}, max={info.max}")
for dtype in [np.float16, np.float32, np.float64, np.float128]:
    info = np.finfo(dtype)
    print(f"{dtype}: min={info.min}, max={info.max}")<jupyter_output><class 'numpy.int8'>: min=-128, max=127
<class 'numpy.int16'>: min=-32768, max=32767
<class 'numpy.int32'>: min=-2147483648, max=2147483647
<class 'numpy.int64'>: min=-9223372036854775808, max=9223372036854775807
<class 'numpy.float16'>: min=-65504.0, max=65504.0
<class 'numpy.float32'>: min=-3.4028234663852886e+38, max=3.4028234663852886e+38
<class 'numpy.float64'>: min=-1.7976931348623157e+308, max=1.7976931348623157e+308
<class 'numpy.float128'>: min=-inf, max=inf<jupyter_text>49. 打印数组所有元素（不省略）<jupyter_code>with np.printoptions(threshold=np.inf):
    z = np.ones((10, 10))
    print(z)<jupyter_output>[[1. 1. 1. 1. 1. 1. 1. 1. 1. 1.]
 [1. 1. 1. 1. 1. 1. 1. 1. 1. 1.]
 [1. 1. 1. 1. 1. 1. 1. 1. 1. 1.]
 [1. 1. 1. 1. 1. 1. 1. 1. 1. 1.]
 [1. 1. 1. 1. 1. 1. 1. 1. 1. 1.]
 [1. 1. 1. 1. 1. 1. 1. 1. 1. 1.]
 [1. 1. 1. 1. 1. 1. 1. 1. 1. 1.]
 [1. 1. 1. 1. 1. 1. 1. 1. 1. 1.]
 [1. 1. 1. 1. 1. 1. 1. 1. 1. 1.]
 [1. 1. 1. 1. 1. 1. 1. 1. 1. 1.]]<jupyter_text>50. 给定一个数，在数组中找出距离其最近的数<jupyter_code># 给定的数组
z = np.random.uniform(0, 1, 10)
z
# 给定的数
x = 0.5
# 定位距离最近数的位置
index = np.abs(z - x).argmin()
# 找到该数字
z[index]<jupyter_output><empty_output><jupyter_text>51. 创建一个结构化的数组，其元素为一个座标(x,y)和一个颜色参数(r,g,b)和46题类似。>另外，这可以是一个像素点的表示方式<jupyter_code>z = np.zeros(10, [('position', [('x', float, 1),
                               ('y', float, 1)]),
                 ('color', [('r', float, 1),
                            ('g', float, 1),
                            ('b', float, 1)])
                 ]
            )
z<jupyter_output><empty_output><jupyter_text>52. 考虑一个形状为（10， 2）的随机向量，若其代表二维平面中的点，求各点之间的距离<jupyter_code>z = np.random.random((10, 2))
x, y = np.atleast_2d(z[:, 0], z[:, 1])
d = np.sqrt((x - x.T)**2 + (y - y.T)**2)
d<jupyter_output><empty_output><jupyter_text>这里使用`np.atleast_2d`使得我们得到的`x`， `y`直接就是2维的数组，方便了我们后面直接使用`broadcasting`.我们也可以采用下面的方法代替这行，但是不够简洁：```pythonx = z[:, 0].reshape(10, 1)y = z[:, 1].reshape(1, 10)```此外我们也可以使用`scipy`内置的函数，其效率要高一些。<jupyter_code>import scipy
import scipy.spatial

d = scipy.spatial.distance.cdist(z, z)
d<jupyter_output><empty_output><jupyter_text>53. 将一个32位的浮点数数组，（不使用额外内存）转化为32为的整数数组<jupyter_code>z = np.zeros(10, dtype=np.float32)
z
z = z.astype(np.int32, copy=False)
z<jupyter_output><empty_output><jupyter_text>54. 如何读取下面的文件```1, 2, 3, 4, 56,  ,  , 7, 8 ,  , 9,10,11```<jupyter_code>from io import StringIO
# “假”的文件
s = StringIO("""1, 2, 3, 4, 5\n
                6,  ,  , 7, 8\n
                 ,  , 9,10,11\n""")
z = np.genfromtxt(s, delimiter=",", missing_values=' ')
z<jupyter_output><empty_output><jupyter_text>55. Python内置有`enumerate`,Numpy中与之对应的是？<jupyter_code>Z = np.arange(9).reshape(3,3)
for index, value in np.ndenumerate(Z):
    print(index, value)
for index in np.ndindex(Z.shape):
    print(index, Z[index])<jupyter_output>(0, 0) 0
(0, 1) 1
(0, 2) 2
(1, 0) 3
(1, 1) 4
(1, 2) 5
(2, 0) 6
(2, 1) 7
(2, 2) 8<jupyter_text>56. 生成二维高斯分布<jupyter_code>X, Y = np.meshgrid(np.linspace(-1,1,10), np.linspace(-1,1,10))
D = np.sqrt(X*X+Y*Y)
sigma, mu = 1.0, 0.0
G = np.exp(-( (D-mu)**2 / ( 2.0 * sigma**2 ) ) )
G<jupyter_output><empty_output><jupyter_text>57. 随机地在二维数组中放置p个元素<jupyter_code>n = 5
p = 3
z = np.zeros((n, n))
np.put(z, np.random.choice(range(n*n), p), 1)
z<jupyter_output><empty_output><jupyter_text>58. 矩阵每行进行中心化（减去均值）<jupyter_code># 1, 答案的方法
z = np.arange(10).reshape(2, 5)
z
z_new = z - z.mean(axis=1, keepdims=True)
z_new<jupyter_output><empty_output><jupyter_text>注意这里，设置`keepdims`可以方便进行`broadcasting`, 免去手动`reshape`的流程。我们也可以考虑对矩阵每一行应用一个中心化的函数来完成任务。<jupyter_code># 2, apply方法
def centered(xs):
    return xs - xs.mean()

z_new = np.apply_along_axis(centered, 1, z)
z_new<jupyter_output><empty_output><jupyter_text>59. 根据某列数据来排列数组<jupyter_code>z = np.random.randint(0, 10, (3, 3))
z
# 根据第二列顺序排列
z[z[:, 1].argsort(), ]<jupyter_output><empty_output><jupyter_text>60. 判断二维数组是否含有空列(全为0)<jupyter_code>z = np.random.randint(0, 3, (3, 10))
z
print((~z.any(axis=0)).any())<jupyter_output>False<jupyter_text>一旦有空列的时候， `z.any(axis=0)`返回`False`， 即`~z.any(axis=0)`返回`True`， 之后再应用`any`, 则比返回`True`。 反之，若无任何空列，`~z.any(axis=0)`全部返回`False`， 应用`any`，依旧返回`False`。  61. 给定一个数，在数组中找出距离其最近的数与50题重复.  62. 考虑两个数组，形状分别是（3， 1）， （1， 3），如何使用迭代器将其相加？<jupyter_code>A = np.arange(3).reshape(3,1)
B = np.arange(3).reshape(1,3)
it = np.nditer([A,B,None])
for x,y,z in it: z[...] = x + y
print(it.operands[2])<jupyter_output>[[0 1 2]
 [1 2 3]
 [2 3 4]]<jupyter_text>63. 创建一个带有名称属性的数组类<jupyter_code>class NamedArray(np.ndarray):
    def __new__(cls, array, name="no name"):
        obj = np.asarray(array).view(cls)
        obj.name = name
        return obj
    def __array_finalize__(self, obj):
        if obj is None: return
        self.info = getattr(obj, 'name', "no name")

Z = NamedArray(np.arange(10), "range_10")
print (Z.name)<jupyter_output>range_10<jupyter_text>64. 给定一个数值向量，和一个索引向量，根据后者的索引，在前者对应位置加1（注意重复索引）<jupyter_code># Author: <NAME>
Z = np.ones(10)
I = np.random.randint(0,len(Z),20)

Z_new = Z + np.bincount(I, minlength=len(Z))
Z_new
# Another solution
# Author: <NAME>
np.add.at(Z, I, 1)
Z<jupyter_output><empty_output><jupyter_text>65. 根据索引列表I，对数值列表X进行累加，得到F<jupyter_code>X = [1,2,3,4,5,6]
I = [1,3,9,3,4,1]
F = np.bincount(I,X)
print(F)<jupyter_output>[0. 7. 0. 6. 5. 0. 0. 0. 0. 3.]<jupyter_text>这里`bincount`的用法有点绕...让我们举个例子先:-)我们把`I`中出现的数字比作个人的银行账户编号，可以看到这里最大的编号为9，所以我们暂时可以只考虑编号0~9的账户情况， 这10个账户，正好对应最后得到F的10个位置。进一步地，`I`与`X`结合，可以看作这些银行账户交易的流水，其中`I`为账户编号，`X`为对应的金额。比如，因为`I[0]=1`，我们知道是账户1发生交易，对应的`X[0]=1`，所以账户1的金额要加1；此外账户1还发生一次交易（`I[5]=1`）, 对应的金额`X[5] = 6`，所以这段时间账户1总的金额就是`6 + 1 = 7`，所以得到`F[1] = 7`.简言之，我们的任务就是根据`X`和`I`组成的交易流水，来计算各个账户总的金额。  66. 给定一张照片（w, h, 3），计算其中不同颜色的个数<jupyter_code># Author: <NAME>

w,h = 16, 16
I = np.random.randint(0,2,(h,w,3)).astype(np.ubyte)
# 注意我们这里必须先乘256*256，否则会爆栈 
F = I[...,0]*(256*256) + I[...,1]*256 +I[...,2]
n = len(np.unique(F))
print(n)<jupyter_output>8<jupyter_text>67. 考虑一个四维数组，计算后两个轴上的元素和<jupyter_code>A = np.random.randint(0,10,(3,4,3,4))
A.sum(axis=(-2,-1))<jupyter_output><empty_output><jupyter_text>68. 给定向量D，根据索引数组S得到子集，计算子集上的均值<jupyter_code>D = np.random.uniform(0,1,100)
S = np.random.randint(0,10,100)
D_sums = np.bincount(S, weights=D)
D_counts = np.bincount(S)
D_means = D_sums / D_counts
print(D_means)<jupyter_output>[0.58150261 0.55134568 0.57372635 0.46632861 0.51824552 0.5358013
 0.42991891 0.46169025 0.39369914 0.44701464]<jupyter_text>结合65题给出的例子，在那里是根据流水计算各个账户总的金额，这里是计算各个账户每次交易的平均金额，也就是该账户总的金额除以其交易的次数。  69. 获取矩阵点乘(dot product)结果的对角线元素<jupyter_code># Author: <NAME>

A = np.random.uniform(0,1,(5,5))
B = np.random.uniform(0,1,(5,5))

# 慢的版本
np.diag(np.dot(A, B))

# 快的版本
np.sum(A * B.T, axis=1)

# 更快的版本
np.einsum("ij,ji->i", A, B)<jupyter_output><empty_output><jupyter_text>70. 如何在数组[1, 2, 3, 4, 5]每两个值的中间添加三个0<jupyter_code>z = np.array([1, 2, 3, 4, 5])
nz = 3  # 0的个数
v = np.zeros(len(z) + nz*(len(z)-1))
v[::nz+1] = z
v<jupyter_output><empty_output><jupyter_text>71. 维度分别为（5， 5， 3）， （5， 5）的两个数组相乘<jupyter_code>A = np.ones((5,5,3))
B = 2*np.ones((5,5))
print(A * B[:,:,None])<jupyter_output>[[[2. 2. 2.]
  [2. 2. 2.]
  [2. 2. 2.]
  [2. 2. 2.]
  [2. 2. 2.]]

 [[2. 2. 2.]
  [2. 2. 2.]
  [2. 2. 2.]
  [2. 2. 2.]
  [2. 2. 2.]]

 [[2. 2. 2.]
  [2. 2. 2.]
  [2. 2. 2.]
  [2. 2. 2.]
  [2. 2. 2.]]

 [[2. 2. 2.]
  [2. 2. 2.]
  [2. 2. 2.]
  [2. 2. 2.]
  [2. 2. 2.]]

 [[2. 2. 2.]
  [2. 2. 2.]
  [2. 2. 2.]
  [2. 2. 2.]
  [2. 2. 2.]]]<jupyter_text>72. 交换数组的两行<jupyter_code>A = np.arange(25).reshape((5, 5))
A
# 交换第一、二两行
A[[0, 1]] = A[[1, 0]]
A<jupyter_output><empty_output><jupyter_text>73. 给定10个三元组描述10个三角形，找出所有边的集合<jupyter_code>faces = np.random.randint(0,100,(10,3))
F = np.roll(faces.repeat(2,axis=1),-1,axis=1)
F = F.reshape(len(F)*3,2)
F = np.sort(F,axis=1)
G = F.view( dtype=[('p0',F.dtype),('p1',F.dtype)] )
G = np.unique(G)
print(G)<jupyter_output>[( 6, 31) ( 6, 96) ( 7, 30) ( 7, 82) (11, 18) (11, 48) (15, 28) (18, 48)
 (24, 29) (24, 65) (25, 51) (25, 84) (28, 28) (29, 32) (29, 65) (30, 82)
 (31, 96) (32, 65) (43, 77) (43, 88) (46, 54) (46, 71) (51, 84) (54, 71)
 (68, 83) (68, 89) (77, 88) (83, 89)]<jupyter_text>感觉这里的方法比较巧妙，可以将每一步拆解来理解怎么将每条边抽取出来。之后比较细节的地方就是对描述“边”的二元组排序(如果不排序，后面比较的时候就会出现(a, b)与（b, a）不是同一条边的错误判断)，之后通过`view`转化类型，方便比较（使用`np.unique`）  74. 给定A，我们有C = np.bincount(A), 那么，给定C，如何找到对应的A？<jupyter_code>C = np.bincount([1,1,2,3,4,4,6])
A = np.repeat(np.arange(len(C)), C)
print(A)<jupyter_output>[1 1 2 3 4 4 6]<jupyter_text>75. 用滑动窗口计算平均值<jupyter_code>def moving_average(a, n=3) :
    ret = np.cumsum(a, dtype=float)
    ret[n:] = ret[n:] - ret[:-n]
    return ret[n - 1:] / n
Z = np.arange(20)
print(moving_average(Z, n=3))<jupyter_output>[ 1.  2.  3.  4.  5.  6.  7.  8.  9. 10. 11. 12. 13. 14. 15. 16. 17. 18.]<jupyter_text>76. 给定一个一维数组，组建一个二维数组，使得第一行为Z[0], Z[1], Z[2], 第二行为Z[1], Z[2], Z[3], 依此类推，最后一行为Z[-3], Z[-2], Z[-1]<jupyter_code>from numpy.lib import stride_tricks

def rolling(a, window):
    shape = (a.size - window + 1, window)
    strides = (a.itemsize, a.itemsize)
    return stride_tricks.as_strided(a, shape=shape, strides=strides)
Z = rolling(np.arange(10), 3)
print(Z)<jupyter_output>[[0 1 2]
 [1 2 3]
 [2 3 4]
 [3 4 5]
 [4 5 6]
 [5 6 7]
 [6 7 8]
 [7 8 9]]<jupyter_text>77. 如何原地对布尔值取反，如何原地改变数字的正负<jupyter_code>Z = np.random.randint(0,2,100)
np.logical_not(Z, out=Z)

Z = np.random.uniform(-1.0,1.0,100)
np.negative(Z, out=Z)<jupyter_output><empty_output><jupyter_text>78. 计算点p到各个直线i的距离, 其中直线由(P0[i]， P1[i])表示，P0，P1为一系列对应的点<jupyter_code>def distance(P0, P1, p):
    T = P1 - P0
    L = (T**2).sum(axis=1)
    U = -((P0[:,0]-p[...,0])*T[:,0] + (P0[:,1]-p[...,1])*T[:,1]) / L
    U = U.reshape(len(U),1)
    D = P0 + U*T - p
    return np.sqrt((D**2).sum(axis=1))

P0 = np.random.uniform(-10,10,(10,2))
P1 = np.random.uniform(-10,10,(10,2))
p  = np.random.uniform(-10,10,( 1,2))
print(distance(P0, P1, p))<jupyter_output>[ 1.01154163  5.12606935 13.94958511 22.07140895  0.94980679 11.10441586
 10.13624982 15.90978826 12.76884591  7.35750952]<jupyter_text>79. 接上题，如何计算P0中各点P0[j]到各直线（P0[i], P1[i]）的距离<jupyter_code># based on distance function from previous question
P0 = np.random.uniform(-10, 10, (10,2))
P1 = np.random.uniform(-10,10,(10,2))
p = np.random.uniform(-10, 10, (10,2))
print(np.array([distance(P0,P1,p_i) for p_i in p]))<jupyter_output>[[ 3.5734595   0.66180336  7.3187876   4.99413157  0.96165362  1.50776605
  15.24621075  5.09372975  5.79926051  2.37223415]
 [ 9.65216196  3.90422416  0.02454316  5.90288419  6.93066482  5.33370707
   4.85444051  7.35964798  7.41460408  6.10650993]
 [ 3.0170691   9.17194136  4.03658393  0.93905036 11.63440516  9.62787647
   2.93837077  6.05884677 13.55270024  0.66358603]
 [ 6.64712401  9.12738601  5.142417    5.57297746 12.16615989 10.53392643
   0.31688742 10.17275773 12.38143328  2.29469197]
 [ 1.29889259  9.25138092  3.58160414  1.21483096 11.44657219  9.26597142
   4.10370268  4.18161798 14.15205666  2.07913113]
 [ 0.9143175   0.64478816  6.63477487  7.52739507  1.96629743  0.70986043
  15.51887126  6.57975813  7.63913062  0.12958737]
 [14.36169595  8.51086264 13.08230922  3.56073338  5.90285668  7.66843812
  17.43569283  2.12028403  3.62911512 13.19184398]
 [14.54713139  1.95977899  0.74333133 10.87761572  5.58552605  4.39352621
   3.75662835 10.64759725  4.38286275 10.59080599]
[...]<jupyter_text>80. 给定任意一个数组，编写一个函数，接受数组和一个元素为参数，返回以元素为中心的子集（必要的时候可以进行填充）<jupyter_code># Author: <NAME>

Z = np.random.randint(0,10,(10,10))
shape = (5,5)
fill  = 0
position = (1,1)

R = np.ones(shape, dtype=Z.dtype)*fill
P  = np.array(list(position)).astype(int)
Rs = np.array(list(R.shape)).astype(int)
Zs = np.array(list(Z.shape)).astype(int)

R_start = np.zeros((len(shape),)).astype(int)
R_stop  = np.array(list(shape)).astype(int)
Z_start = (P-Rs//2)
Z_stop  = (P+Rs//2)+Rs%2

R_start = (R_start - np.minimum(Z_start,0)).tolist()
Z_start = (np.maximum(Z_start,0)).tolist()
R_stop = np.maximum(R_start, (R_stop - np.maximum(Z_stop-Zs,0))).tolist()
Z_stop = (np.minimum(Z_stop,Zs)).tolist()

r = [slice(start,stop) for start,stop in zip(R_start,R_stop)]
z = [slice(start,stop) for start,stop in zip(Z_start,Z_stop)]
R[r] = Z[z]
print(Z)
print(R)<jupyter_output>[[7 9 1 5 1 6 6 3 7 6]
 [9 5 1 4 5 8 5 4 4 7]
 [3 8 4 7 5 1 5 6 0 9]
 [2 9 9 5 4 1 1 4 7 8]
 [4 2 8 8 1 4 0 4 5 3]
 [2 9 5 0 4 6 9 6 9 0]
 [2 0 0 3 1 1 4 5 9 2]
 [1 4 4 7 2 7 1 5 6 3]
 [3 3 4 6 6 1 9 8 4 1]
 [7 9 2 1 8 9 7 7 4 5]]
[[0 0 0 0 0]
 [0 7 9 1 5]
 [0 9 5 1 4]
 [0 3 8 4 7]
 [0 2 9 9 5]]<jupyter_text>PS: 感觉难度为三星的题目（64题及之后）很多出的不太好...考察的是更加灵活地运用Numpy，逻辑是没问题，但是缺乏具体的示例，没有依托实际的问题，就显得比较空洞Orz  81. 有数组Z = [1,2,3,4,5,6,7,8,9,10,11,12,13,14]， 如何生成 = [[1,2,3,4], [2,3,4,5], [3,4,5,6], ..., [11,12,13,14]]？<jupyter_code># 1， 答案的方法
Z = np.arange(1,15,dtype=np.uint32)
R = stride_tricks.as_strided(Z,(11,4),(4,4))
print(R)
# 2， 76题的一个特殊形式
z = np.arange(1, 15)
rolling(z, 4)<jupyter_output><empty_output><jupyter_text>82. 计算矩阵的秩<jupyter_code># 1， 答案的方法
Z = np.random.uniform(0,1,(10,10))
U, S, V = np.linalg.svd(Z) # Singular Value Decomposition
rank = np.sum(S > 1e-10)
print(rank)
# 2， 调用API
np.linalg.matrix_rank(Z)<jupyter_output><empty_output><jupyter_text>83. 找出数组中的众数<jupyter_code>Z = np.random.randint(0,10,50)
Z
print(np.bincount(Z).argmax())<jupyter_output>0<jupyter_text>如果不限制在Numpy之内，我们可以直接调用Scipy提供的API<jupyter_code>from scipy import stats
stats.mode(Z)<jupyter_output><empty_output><jupyter_text>84. 从10x10的矩阵中抽取出所有的3x3矩阵<jupyter_code>Z = np.random.randint(0,5,(10,10))
n = 3
i = 1 + (Z.shape[0]-3)
j = 1 + (Z.shape[1]-3)
C = stride_tricks.as_strided(Z, shape=(i, j, n, n), strides=Z.strides + Z.strides)
print(C)<jupyter_output>[[[[1 0 3]
   [4 4 1]
   [4 1 4]]

  [[0 3 1]
   [4 1 1]
   [1 4 0]]

  [[3 1 3]
   [1 1 2]
   [4 0 4]]

  [[1 3 3]
   [1 2 2]
   [0 4 2]]

  [[3 3 2]
   [2 2 1]
   [4 2 1]]

  [[3 2 0]
   [2 1 1]
   [2 1 0]]

  [[2 0 1]
   [1 1 1]
   [1 0 1]]

  [[0 1 2]
   [1 1 1]
   [0 1 4]]]


 [[[4 4 1]
   [4 1 4]
   [1 1 1]]

  [[4 1 1]
   [1 4 0]
   [1 1 1]]

  [[1 1 2]
   [4 0 4]
   [1 1 1]]

  [[1 2 2]
   [0 4 2]
   [1 1 4]]

  [[2 2 1]
   [4 2 1]
   [1 4 4]]

  [[2 1 1]
   [2 1 0]
   [4 4 0]]

  [[1 1 1]
   [1 0 1]
   [4 0 1]]

  [[1 1 1]
   [0 1 4]
   [0 1 4]]]


 [[[4 1 4]
   [1 1 1]
   [4 4 3]]

  [[1 4 0]
   [1 1 1]
   [4 3 3]]

  [[4 0 4]
   [1 1 1]
   [3 3 1]]

  [[0 4 2]
   [1 1 4]
   [3 1 4]]

  [[4 2 1]
   [1 4 4]
   [1 4 4]]

  [[2 1 0]
   [4 4 0]
   [4 4 0]]

  [[1 0 1]
   [4 0 1]
   [4 0 1]]

  [[0 1 4]
   [0 1 4]
   [0 1 0]]]


 [[[1 1 1]
   [4 4 3]
   [2 3 3]]

  [[1 1 1]
   [4 3 3]
   [3 3 1]]

  [[1 1 1]
   [3 3 1]
   [3 1 0]]

  [[1 1 4]
   [3 1 4]
   [1 0 0]]

  [[1 4 4]
   [...]<jupyter_text>85. 构造二维数组的子类，使得Z[i, j] = Z[j, i]<jupyter_code># Author: <NAME>
# Note: only works for 2d array and value setting using indices

class Symetric(np.ndarray):
    def __setitem__(self, index, value):
        i,j = index
        super(Symetric, self).__setitem__((i,j), value)
        super(Symetric, self).__setitem__((j,i), value)

def symetric(Z):
    return np.asarray(Z + Z.T - np.diag(Z.diagonal())).view(Symetric)

S = symetric(np.random.randint(0,10,(5,5)))
S[2,3] = 42
print(S)<jupyter_output>[[ 8 18 10 16 17]
 [18  7  5 14  8]
 [10  5  2 42  4]
 [16 14 42  6 13]
 [17  8  4 13  0]]<jupyter_text>86. 给定p个(n, n)矩阵和p个(n, 1)向量， 计算张量乘法(tensor product)<jupyter_code>p, n = 10, 20
M = np.ones((p,n,n))
V = np.ones((p,n,1))
S = np.tensordot(M, V, axes=[[0, 2], [0, 1]])
print(S)<jupyter_output>[[200.]
 [200.]
 [200.]
 [200.]
 [200.]
 [200.]
 [200.]
 [200.]
 [200.]
 [200.]
 [200.]
 [200.]
 [200.]
 [200.]
 [200.]
 [200.]
 [200.]
 [200.]
 [200.]
 [200.]]<jupyter_text>87. 给定16x16的数组，将其分成4x4的小块，求每块的和<jupyter_code>Z = np.ones((16,16))
k = 4
S = np.add.reduceat(np.add.reduceat(Z, np.arange(0, Z.shape[0], k), axis=0),
                                       np.arange(0, Z.shape[1], k), axis=1)
print(S)<jupyter_output>[[16. 16. 16. 16.]
 [16. 16. 16. 16.]
 [16. 16. 16. 16.]
 [16. 16. 16. 16.]]<jupyter_text>88. 用数组实现生存游戏<jupyter_code>def iterate(Z):
    # Count neighbours
    N = (Z[0:-2,0:-2] + Z[0:-2,1:-1] + Z[0:-2,2:] +
         Z[1:-1,0:-2]                + Z[1:-1,2:] +
         Z[2:  ,0:-2] + Z[2:  ,1:-1] + Z[2:  ,2:])

    # Apply rules
    birth = (N==3) & (Z[1:-1,1:-1]==0)
    survive = ((N==2) | (N==3)) & (Z[1:-1,1:-1]==1)
    Z[...] = 0
    Z[1:-1,1:-1][birth | survive] = 1
    return Z

Z = np.random.randint(0,2,(50,50))
for i in range(100): Z = iterate(Z)
print(Z)<jupyter_output>[[0 0 0 ... 0 0 0]
 [0 0 0 ... 0 0 0]
 [0 0 0 ... 0 0 0]
 ...
 [0 0 0 ... 0 0 0]
 [0 0 0 ... 0 0 0]
 [0 0 0 ... 0 0 0]]<jupyter_text>89. 获取数组最大的n个值<jupyter_code>Z = np.arange(10000)
np.random.shuffle(Z)
n = 5
# 较慢
print (Z[np.argsort(Z)[-n:]])
# 较快
print (Z[np.argpartition(-Z,n)[:n]])<jupyter_output>[9999 9997 9998 9996 9995]<jupyter_text>90. 给定任意大小的数组，计算其笛卡尔积<jupyter_code>def cartesian(arrays):
    arrays = [np.asarray(a) for a in arrays]
    shape = (len(x) for x in arrays)

    ix = np.indices(shape, dtype=int)
    ix = ix.reshape(len(arrays), -1).T

    for n, arr in enumerate(arrays):
        ix[:, n] = arrays[n][ix[:, n]]

    return ix

print (cartesian(([1, 2, 3], [4, 5], [6, 7])))<jupyter_output>[[1 4 6]
 [1 4 7]
 [1 5 6]
 [1 5 7]
 [2 4 6]
 [2 4 7]
 [2 5 6]
 [2 5 7]
 [3 4 6]
 [3 4 7]
 [3 5 6]
 [3 5 7]]<jupyter_text>91. 将一般的数组转化为结构化数组<jupyter_code>Z = np.array([("Hello", 2.5, 3),
              ("World", 3.6, 2)])
Z
R = np.core.records.fromarrays(Z.T, 
                               names='col1, col2, col3',
                               formats = 'S8, f8, i8')
R<jupyter_output><empty_output><jupyter_text>92. 用三种方法计算大向量的三次方<jupyter_code>x = np.random.rand(int(5e7))
%timeit np.power(x,3)
%timeit x*x*x
%timeit np.einsum('i,i,i->i',x,x,x)<jupyter_output>316 ms ± 16.9 ms per loop (mean ± std. dev. of 7 runs, 1 loop each)<jupyter_text>93. 考虑形状（8,3）和（2,2）的两个数组A和B. 如何查找包含B的每一行元素的A行，不考虑B中元素的顺序<jupyter_code>A = np.random.randint(0,5,(8,3))
B = np.random.randint(0,5,(2,2))

C = (A[..., np.newaxis, np.newaxis] == B)
rows = np.where(C.any((3,1)).all(1))[0]
print(rows)<jupyter_output>[2 3 4 5 6]<jupyter_text>94. 给定（10， 3）的矩阵， 找出包含不同元素的行<jupyter_code>Z = np.random.randint(0,5,(10,3))
Z
# 适用于任意数据类型
E = np.all(Z[:,1:] == Z[:,:-1], axis=1)
U = Z[~E]
U
# 仅适用于数值类型
U = Z[Z.max(axis=1) != Z.min(axis=1),:]
U<jupyter_output><empty_output><jupyter_text>95. 将给定的整数向量转化为二进制矩阵<jupyter_code>I = np.array([0, 1, 2, 3, 15, 16, 32, 64, 128], dtype=np.uint8)
print(np.unpackbits(I[:, np.newaxis], axis=1))<jupyter_output>[[0 0 0 0 0 0 0 0]
 [0 0 0 0 0 0 0 1]
 [0 0 0 0 0 0 1 0]
 [0 0 0 0 0 0 1 1]
 [0 0 0 0 1 1 1 1]
 [0 0 0 1 0 0 0 0]
 [0 0 1 0 0 0 0 0]
 [0 1 0 0 0 0 0 0]
 [1 0 0 0 0 0 0 0]]<jupyter_text>96. 给定二维数组，抽取所有不同的行<jupyter_code>Z = np.random.randint(0,2,(6,3))
Z
uZ = np.unique(Z, axis=0)
uZ<jupyter_output><empty_output><jupyter_text>97. 考虑两个数组A，B， 使用np.einsum写出矩阵间的outer, inner, sum, mul函数<jupyter_code>A = np.random.uniform(0,1,10)
B = np.random.uniform(0,1,10)

np.einsum('i->', A)       # np.sum(A)
np.einsum('i,i->i', A, B) # A * B
np.einsum('i,i', A, B)    # np.inner(A, B)
np.einsum('i,j->ij', A, B)    # np.outer(A, B)<jupyter_output><empty_output><jupyter_text>98. 用两个向量(X, Y)描述一条轨道，如何对其进行等距抽样<jupyter_code>phi = np.arange(0, 10*np.pi, 0.1)
a = 1
x = a*phi*np.cos(phi)
y = a*phi*np.sin(phi)

dr = (np.diff(x)**2 + np.diff(y)**2)**.5 # segment lengths
r = np.zeros_like(x)
r[1:] = np.cumsum(dr)                # integrate path
r_int = np.linspace(0, r.max(), 200) # regular spaced path
x_int = np.interp(r_int, r, x)       # integrate path
y_int = np.interp(r_int, r, y)<jupyter_output><empty_output><jupyter_text>99. 给定一个二维数组和一个整数n，提取所有仅包含整数，且元素和为n的行<jupyter_code>X = np.asarray([[1.0, 0.0, 3.0, 8.0],
                [2.0, 0.0, 1.0, 1.0],
                [1.5, 2.5, 1.0, 0.0]])
n = 4
M = np.logical_and.reduce(np.mod(X, 1) == 0, axis=-1)
M &= (X.sum(axis=-1) == n)
print(X[M])<jupyter_output>[[2. 0. 1. 1.]]<jupyter_text>100. 给定一个向量，计算其均值的95%的置信区间<jupyter_code>X = np.random.randn(100) 
N = 1000  # 再抽样次数
idx = np.random.randint(0, X.size, (N, X.size))
means = X[idx].mean(axis=1)
confint = np.percentile(means, [2.5, 97.5])
print(confint)<jupyter_output>[-0.29266392  0.11041998]
{'fraction_non_alphanumeric': 0.19301286391333786, 'fraction_numerical': 0.10288422477995937, 'mean_word_length': 4.6375572519083965, 'pattern_counts': {'":': 0, '<': 504, '<?xml version=': 0, '>': 491, 'https://': 3, 'lorem ipsum': 0, 'www.': 0, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 14, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'chain_length': '124', 'dir': 'jupyter-structured-clean-dedup', 'id': '320042', 'license': 'MIT', 'n_tokens_mistral': 22629, 'n_tokens_neox': 21183, 'n_words': 3108, 'path': '100 Numpy Exercises.ipynb', 'repo_name': 'shenxiangzhuang/Oh-Numpy', 'size': '36983'}