目录
- 元素操作
- Basic reductions
- Broadcasting
- 阵列形状操作
- 排序数据
- 总结
使用标量:
>>> a = np.array([1, 2, 3, 4])
>>> a   1
array([2, 3, 4, 5])
>>> 2**a
array([ 2,  4,  8, 16])
所有算术都按元素进行操作:
>>> b = np.ones(4)   1
>>> a - b
array([-1.,  0.,  1.,  2.])
>>> a * b
array([2.,  4.,  6.,  8.])
>>> j = np.arange(5)
>>> 2**(j   1) - j
array([ 2,  3,  6, 13, 28])
这些操作当然比在纯 python 中执行要快得多:
>>> a = np.arange(10000)
>>> %timeit a   1  
10000 loops, best of 3: 24.3 us per loop
>>> l = range(10000)
>>> %timeit [i 1 for i in l] 
1000 loops, best of 3: 861 us per loop
数组乘法不是矩阵乘法:
>>> c = np.ones((3, 3))
>>> c * c                   # 不是矩阵乘法!
array([[1.,  1.,  1.],
       [1.,  1.,  1.],
       [1.,  1.,  1.]])
矩阵乘法:
>>> c.dot(c)
array([[3.,  3.,  3.],
       [3.,  3.,  3.],
       [3.,  3.,  3.]])
其他操作
比较:
>>> a = np.array([1, 2, 3, 4])
>>> b = np.array([4, 2, 2, 4])
>>> a == b
array([False,  True, False,  True])
>>> a > b
array([False, False,  True, False])
数组比较:
>>> a = np.array([1, 2, 3, 4])
>>> b = np.array([4, 2, 2, 4])
>>> c = np.array([1, 2, 3, 4])
>>> np.array_equal(a, b)
False
>>> np.array_equal(a, c)
True
逻辑运算:
>>>
>>> a = np.array([1, 1, 0, 0], dtype=bool)
>>> b = np.array([1, 0, 1, 0], dtype=bool)
>>> np.logical_or(a, b)
array([ True,  True,  True, False])
>>> np.logical_and(a, b)
array([ True, False, False, False])
超越函数:
>>>
>>> a = np.arange(5)
>>> np.sin(a)
array([ 0.        ,  0.84147098,  0.90929743,  0.14112001, -0.7568025 ])
>>> np.log(a)
array([       -inf,  0.        ,  0.69314718,  1.09861229,  1.38629436])
>>> np.exp(a)
array([  1.        ,   2.71828183,   7.3890561 ,  20.08553692,  54.59815003])
形状不匹配
>>>
>>> a = np.arange(5)
>>> a   np.array([1, 2])  
ValueError: operands could not be broadcast together with shapes (5,) (2,) 
换位:
>>>
>>> a = np.triu(np.ones((3, 3)), 1)   #  help(np.triu)
>>> a
array([[0.,  1.,  1.],
       [0.,  0.,  1.],
       [0.,  0.,  0.]])
# triu(m, k),保留上三角,左下部分调为0. k=0 表示主对角线。
>>> a.T				# 转置
array([[0.,  0.,  0.],
       [1.,  0.,  0.],
       [1.,  1.,  0.]])
np.reshape
>>>
>>> a = np.arange(9).reshape(3, 3)
>>> a.T[0, 2] = 999
>>> a.T
array([[  0,   3, 999],
       [  1,   4,   7],
       [  2,   5,   8]])
>>> a
array([[  0,   1,   2],
       [  3,   4,   5],
       [999,   7,   8]])
线性代数
该子模块NumPy.linalg实现了基本的线性代数,例如求解线性系统、奇异值分解等。但是,它并不一定总是高效,因此我们一般使用scipy.linalg
1.2.2 Basic reductions计算总和>>>
>>> x = np.array([1, 2, 3, 4])
>>> np.sum(x)
10
>>> x.sum()
10

按行和按列求和:
>>>
>>> x = np.array([[1, 1], [2, 2]])
>>> x
array([[1, 1],
       [2, 2]])
>>> x.sum(axis=0)   # columns (first dimension)
array([3, 3])
>>> x[:, 0].sum(), x[:, 1].sum()
(3, 3)
>>> x.sum(axis=1)   # rows (second dimension)
array([2, 4])
>>> x[0, :].sum(), x[1, :].sum()
(2, 4)
更高维度:
>>>
x = np.random.rand(2, 2, 2)
x
Out[14]: 
array([[[0.31174025, 0.11658995],
        [0.27243086, 0.87529974]],
       [[0.7719098 , 0.30237664],
        [0.45840615, 0.05789042]]])
x.sum(axis=2)
Out[15]: 
array([[0.4283302 , 1.14773061],
       [1.07428645, 0.51629657]])
x.sum(axis=2)[0,1]
Out[16]: 1.147730606111291
x[0, 1, :].sum()
Out[17]: 1.147730606111291
其它
极值:
>>>
x = np.arange(1,17).reshape(4,4)
x
Out[23]: 
array([[ 1,  2,  3,  4],
       [ 5,  6,  7,  8],
       [ 9, 10, 11, 12],
       [13, 14, 15, 16]])
x.min()
Out[24]: 1
x.max()
Out[25]: 16
x.argmin()          # index of minimum
Out[26]: 0
x.argmax()					# index of maximum
Out[27]: 15
逻辑运算:
>>>
>>> np.all([True, True, False])
False
>>> np.any([True, True, False])
True
可用于数组比较:
>>>
>>> a = np.zeros((100, 100))
>>> np.any(a != 0)
False
>>> np.all(a == a)
True
>>> a = np.array([1, 2, 3, 2])
>>> b = np.array([2, 2, 3, 2])
>>> c = np.array([6, 4, 4, 5])
>>> ((a <= b) & (b <= c)).all()
True
统计数据:
>>>
>>> x = np.array([1, 2, 3, 1])
>>> y = np.array([[1, 2, 3], [5, 6, 1]])
>>> x.mean()
1.75
>>> np.median(x)
1.5
>>> np.median(y, axis=-1) # last axis
array([2.,  5.])
>>> x.std()          # full population standard dev.
0.82915619758884995
工作示例:使用随机游走算法

让我们考虑一个简单的一维随机游走过程:在每个时间步,步行者以相等的概率向右或向左跳跃。
我们有兴趣在 t 左跳或右跳后找到与随机步行者原点的距离?我们将模拟许多“步行者”来找到这个定律,我们将使用数组计算技巧来做到这一点:我们将创建一个二维数组,

>>>
>>> n_stories = 1000 # number of walkers
>>> t_max = 200      # 时间
我们随机选择步行的所有步骤 1 或 -1:
>>>
>>> t = np.arange(t_max)
>>> steps = 2 * np.random.randint(0, 1   1, (n_stories, t_max)) - 1 #  1 because the high value is exclusive
>>> np.unique(steps) # 验证,所有步为1或-1
array([-1,  1])
我们通过对时间的步求和来得到距离:
>>>
>>> positions = np.cumsum(steps, axis=1) # axis = 1: dimension of time
>>> sq_distance = positions**2
我们得到故事轴的平均值:
>>>
>>> mean_sq_distance = np.mean(sq_distance, axis=0)
结果:

我们得到的结论:RMS 距离随着时间的平方根而增长!
1.2.3 Broadcasting- numpy数组的基本操作(加法等)是元素级的
- 这适用于相同大小的数组。尽管如此,也可以对不同大小的数组进行操作,如果NumPy可以转换这些数组,以便它们大小相同:这种转换称为Broadcasting。
下图给出了一个Broadcasting的例子:

让我们验证一下:
>>>
>>> a = np.tile(np.arange(0, 40, 10), (3, 1)).T
>>> a
array([[ 0,  0,  0],
       [10, 10, 10],
       [20, 20, 20],
       [30, 30, 30]])
>>> b = np.array([0, 1, 2])
>>> a   b
array([[ 0,  1,  2],
       [10, 11, 12],
       [20, 21, 22],
       [30, 31, 32]])
我们已经在不知不觉中使用了Broadcasting!:
>>>
>>> a = np.ones((4, 5))
>>> a[0] = 2  # 我们将维数为0的数组赋值给维数为1的数组
>>> a
array([[2.,  2.,  2.,  2.,  2.],
       [1.,  1.,  1.,  1.,  1.],
       [1.,  1.,  1.,  1.,  1.],
       [1.,  1.,  1.,  1.,  1.]])
一个有用的技巧:
>>>
>>> a = np.arange(0, 40, 10)
>>> a.shape
(4,)
>>> a = a[:, np.newaxis]  # adds a new axis -> 2D array
>>> a.shape
(4, 1)
>>> a
array([[ 0],
       [10],
       [20],
       [30]])
>>> a   b
array([[ 0,  1,  2],
       [10, 11, 12],
       [20, 21, 22],
       [30, 31, 32]])
Broadcasting 看起来有点神奇,但当我们要解决输出数据是比输入数据多维的数组的问题时,使用它实际上是很自然的。
许多基于网格或基于网络的问题也可以使用Broadcasting。例如,如果我们想计算 5x5 网格上点到原点的距离,我们可以这样做
>>>
>>> x, y = np.arange(5), np.arange(5)[:, np.newaxis]
>>> distance = np.sqrt(x ** 2   y ** 2)
>>> distance
array([[0.        ,  1.        ,  2.        ,  3.        ,  4.        ],
       [1.        ,  1.41421356,  2.23606798,  3.16227766,  4.12310563],
       [2.        ,  2.23606798,  2.82842712,  3.60555128,  4.47213595],
       [3.        ,  3.16227766,  3.60555128,  4.24264069,  5.        ],
       [4.        ,  4.12310563,  4.47213595,  5.        ,  5.65685425]])
或颜色:
>>>
>>> plt.pcolor(distance)    
>>> plt.colorbar()    

备注:该numpy.ogrid()函数允许直接创建上向量 x 和 y,具有两个“重要维度”:
>>>
>>> x, y = np.ogrid[0:5, 0:5]
>>> x, y
(array([[0],
       [1],
       [2],
       [3],
       [4]]), array([[0, 1, 2, 3, 4]]))
>>> x.shape, y.shape
((5, 1), (1, 5))
>>> distance = np.sqrt(x ** 2   y ** 2)
因此一旦我们需要在网格上处理计算,np.ogrid,用起来非常方便。另一方面,np.mgrid直接为我们不能(或不想)从 Broadcasting 中受益的情况提供索引的矩阵:
>>>
>>> x, y = np.mgrid[0:4, 0:4]
>>> x
array([[0, 0, 0, 0],
       [1, 1, 1, 1],
       [2, 2, 2, 2],
       [3, 3, 3, 3]])
>>> y
array([[0, 1, 2, 3],
       [0, 1, 2, 3],
       [0, 1, 2, 3],
       [0, 1, 2, 3]])
1.2.4 阵列形状操作展平
>>>
>>> a = np.array([[1, 2, 3], [4, 5, 6]])
>>> a.ravel()
array([1, 2, 3, 4, 5, 6])
>>> a.T
array([[1, 4],
       [2, 5],
       [3, 6]])
>>> a.T.ravel()
array([1, 4, 2, 5, 3, 6])
更高的维度:最后的维度是“第一”。
重塑展平的逆操作:
>>>
>>> a.shape
(2, 3)
>>> b = a.ravel()
>>> b = b.reshape((2, 3))
>>> b
array([[1, 2, 3],
       [4, 5, 6]])
或者,
>>>
>>> a.reshape((2, -1))    # unspecified (-1) value is inferred
array([[1, 2, 3],
       [4, 5, 6]])
>>> b[0, 0] = 99
>>> a
array([[99,  2,  3],
       [ 4,  5,  6]])
当心:reshape 也可能返回一个copy!:
>>>
>>> a = np.zeros((3, 2))
>>> b = a.T.reshape(3*2)
>>> b[0] = 9
>>> a
array([[0.,  0.],
       [0.,  0.],
       [0.,  0.]])
要理解这一点,需要了解有关 numpy 数组的内存布局的更多信息。
添加维度使用np.newaxis对象,允许我们向数组添加轴:
>>>
>>> z = np.array([1, 2, 3])
>>> z
array([1, 2, 3])
>>> z[:, np.newaxis]
array([[1],
       [2],
       [3]])
>>> z[np.newaxis, :]
array([[1, 2, 3]])
维度洗牌
>>>
>>> a = np.arange(4*3*2).reshape(4, 3, 2)
>>> a.shape
(4, 3, 2)
>>> a[0, 2, 1]
5
>>> b = a.transpose(1, 2, 0)
>>> b.shape
(3, 2, 4)
>>> b[2, 1, 0]
5
还创建了一个view:
>>>
>>> b[2, 1, 0] = -1
>>> a[0, 2, 1]
-1
调整大小
可以通过以下方式更改数组的大小ndarray.resize:
>>>
>>> a = np.arange(4)
>>> a.resize((8,))
>>> a
array([0, 1, 2, 3, 0, 0, 0, 0])
但是,不得在其它地方提及它:
>>>
>>> b = a
>>> a.resize((4,))   
ValueError: cannot resize an array that has been referenced or is
referencing another array in this way.  Use the resize function
1.2.5。排序数据
沿轴排序:
>>>
>>> a = np.array([[4, 3, 5], [1, 2, 1]])
>>> b = np.sort(a, axis=1)
>>> b
array([[3, 4, 5],
       [1, 1, 2]])
分别对每一行进行排序!
就地排序:
>>>
>>> a.sort(axis=1)
>>> a
array([[3, 4, 5],
       [1, 1, 2]])
用花哨的索引排序:
>>>
>>> a = np.array([4, 3, 1, 2])
>>> j = np.argsort(a)
>>> j
array([2, 3, 1, 0])
>>> a[j]
array([1, 2, 3, 4])
寻找最小值和最大值:
>>>
>>> a = np.array([4, 3, 1, 2])
>>> j_max = np.argmax(a)
>>> j_min = np.argmin(a)
>>> j_max, j_min
(0, 2)
1.2.6 总结
你需要知道哪些才能开始?
- 知道如何创建数组 : array, arange, ones, zeros.
- 用array.shape 查看数组形状,然后使用切片来获得数组的不同view等。用 reshape调整数组的形状或ravel将其展平。
- 获取数组元素的子集和/或使用掩码修改它们的值>>> a[a < 0] = 0
- 了解对数组的各种操作,例如求均值或最大值 ( array.max(), array.mean())。
- 高级用途:掌握整数数组的索引以及Broadcasting。了解更多处理各种数组操作的 NumPy 函数。


























