1.ndarray对象的内部机理
NumPy的ndarray提供了一种将同质化数据块解释为多维数组对象的方式,ndarray如此强大的部分原因是所有数组对象都是数据块的一个跨度视图。ndarray内部由以下内容组成:
a.一个指向数组(一个系统内存块)的指针
b.数据类型或dtype
c.一个表示数组形状的元组;例如,一个10*5的数组,其形状为(10,5)
d.一个跨度元组,其中的整数指的是为了前进到当前维度下一个元素需要“跨度”的字节数;如,一个3*4*5的float(8个字节)数组,其跨度为(160,40,8)
2.NumPy数据类型体系
ints=np.ones(10,dtype=np.uint16)
floats=np.ones(10,dtype=np.float32)
print np.issubdtype(ints.dtype,np.integer)
print np.issubdtype(floats.dtype,np.floating)
结果为:
True
True
调用dtype的mro方法即可查看其所有的父类
print np.float64.mro()
结果为:
[
3.高级重塑
假设有一个一维数组,我们希望将其重新排列为一个矩阵
arr=np.arange(8)
print arr
print arr.reshape((4,2))
结果为:
[0 1 2 3 4 5 6 7]
[[0 1]
[2 3]
[4 5]
[6 7]]
多维数组也能被重塑
print arr.reshape((4,2)).reshape((2,4))
结果为:
[[0 1 2 3]
[4 5 6 7]]
作为参数的形状其中一维可以是-1,它表示该维度的大小由数据本身推断而来
arr2=np.arange(15)
print arr2.reshape((5,-1))
结果为:
[[ 0 1 2]
[ 3 4 5]
[ 6 7 8]
[ 9 10 11]
[12 13 14]]
由于数组的shape属性是一个元组,因此它可以被传入reshape
other_arr=np.ones((3,5))
print other_arr.shape
print arr2.reshape(other_arr.shape)
结果为:
(3L, 5L)
[[ 0 1 2 3 4]
[ 5 6 7 8 9]
[10 11 12 13 14]]
与reshape将一维数组转换为多维数组的运算过程相反的运算通常称为扁平化(flattening)或散开(raveling)
arr3=np.arange(15).reshape((5,3))
print arr3
print arr3.ravel()
结果为:
[[ 0 1 2]
[ 3 4 5]
[ 6 7 8]
[ 9 10 11]
[12 13 14]]
[ 0 1 2 3 4 5 6 7 8 9 10 11 12 13 14]
如果没有必要,ravel不会产生源数据的副本。flatten方法的行为类似于ravel,只不过它总是返回数据的副本
print arr3.flatten()
结果为:
[ 0 1 2 3 4 5 6 7 8 9 10 11 12 13 14]
数组可以被重塑或散开为别的顺序
4.C和Fortran顺序
默认情况下,NumPy数组是按行优先顺序创建的。在空间方面,意味着,对于一个二维数组,每行中的数据项是被存放在相邻内存位置上的。另一种顺序是列优先顺序,意味着每列中的数据项是被存放在相邻内存位置上的。
由于一些历史原因,行和列优先顺序又分别称为C和Fortran顺序。
arr4=np.arange(12).reshape((3,4))
print arr4
print arr4.ravel()
print arr4.ravel('F')
结果为:
[[ 0 1 2 3]
[ 4 5 6 7]
[ 8 9 10 11]]
[ 0 1 2 3 4 5 6 7 8 9 10 11]
[ 0 4 8 1 5 9 2 6 10 3 7 11]
二维或更高数组的重溯过程比较令人费解。C和Fortran顺序的关键区别就是维度的行进顺序:
a.C/行优先顺序:先经过更高的维度(如,轴1会优先于轴0被处理)
b.Fortran/列优先顺序:后经过更高的维度(如,轴0会优先于轴1被处理)
5.数组的合并和拆分
numpy.concatenate可以按指定轴将一个由数组组成的列连接到一起
arr5=np.array([[1,2,3],[4,5,6]])
arr6=np.array([[7,8,9],[10,11,12]])
print np.concatenate([arr5,arr6],axis=0)
print np.concatenate([arr5,arr6],axis=1)
结果为:
[[ 1 2 3]
[ 4 5 6]
[ 7 8 9]
[10 11 12]]
[[ 1 2 3 7 8 9]
[ 4 5 6 10 11 12]]
对于常见的连接操作,NumPy提供了一些比较方便的方法(如vstack和hstack)。因此,上面的运算还可以表达为:
print np.vstack((arr5,arr6))
print np.hstack((arr5,arr6))
结果为:
[[ 1 2 3]
[ 4 5 6]
[ 7 8 9]
[10 11 12]]
[[ 1 2 3 7 8 9]
[ 4 5 6 10 11 12]]
与此相反,split用于将一个数组沿指定轴拆分为多个数组
from numpy.random import randn
arr7=randn(5,2)
print arr7
first,second,third=np.split(arr7,[1,3])
print first
print second
print third
结果为:
[[ 0.33316817 -0.50434988]
[ 1.6748641 0.64469978]
[ 0.1054192 0.80107941]
[ 0.67531015 0.15332466]
[ 1.33885961 2.0612464 ]]
[[ 0.33316817 -0.50434988]]
[[ 1.6748641 0.64469978]
[ 0.1054192 0.80107941]]
[[ 0.67531015 0.15332466]
[ 1.33885961 2.0612464 ]]
5.堆叠辅助类:r_和c_
NumPy命名空间中有两个特殊的对象:r_和c_,他们可以是数组的堆叠操作变的简洁
arr8=np.arange(6)
arr9=arr8.reshape((3,2))
arr10=randn(3,2)
print np.r_[arr9,arr10]
print np.c_[np.r_[arr9,arr10],arr8]
结果为:
[[ 0. 1. ]
[ 2. 3. ]
[ 4. 5. ]
[ 1.41942797 0.28664832]
[-0.17366714 -1.07803222]
[ 0.16150609 -0.09420703]]
[[ 0. 1. 0. ]
[ 2. 3. 1. ]
[ 4. 5. 2. ]
[ 1.41942797 0.28664832 3. ]
[-0.17366714 -1.07803222 4. ]
[ 0.16150609 -0.09420703 5. ]]
此外,它还可以将切片翻译为数组
print np.c_[1:6,-10:-5]
结果为:
[[ 1 -10]
[ 2 -9]
[ 3 -8]
[ 4 -7]
[ 5 -6]]
6.元素的重复操作:tile和repeat
repeat会将数组中的各个元素重复一定次数,从而产生一个更大的数组
arr11=np.arange(3)
print arr11.repeat(3)
结果为:
[0 0 0 1 1 1 2 2 2]
默认情况下,如果传入的是一个整数,则各元素就都会重复那么多次。如果传入的是一组整数,则各元素就可以重复不同的次数
print arr11.repeat([2,3,4])
结果为:
[0 0 1 1 1 2 2 2 2]
对于多维数组,还可以让它们的元素沿指定轴重复
arr12=randn(2,2)
print arr12
print arr12.repeat(2,axis=0)
结果为:
[[-0.42963441 1.04916829]
[ 0.25862366 -0.76362955]]
[[-0.42963441 1.04916829]
[-0.42963441 1.04916829]
[ 0.25862366 -0.76362955]
[ 0.25862366 -0.76362955]]
如果没有设置轴向,则数组会被扁平化。同样,在对多维进行重复时,也可以传入一组整数,这样就会使各切片重复不同的次数
print arr12.repeat([2,3],axis=0)
print arr12.repeat([2,3],axis=1)
结果为:
[[-0.77124211 0.05274718]
[-0.77124211 0.05274718]
[-0.77421856 0.66942701]
[-0.77421856 0.66942701]
[-0.77421856 0.66942701]]
[[-0.77124211 -0.77124211 0.05274718 0.05274718 0.05274718]
[-0.77421856 -0.77421856 0.66942701 0.66942701 0.66942701]]
tile的功能是沿指定轴向堆叠数组的副本。你可以形象地将其想象成“铺瓷砖”
print np.tile(arr12,2)
结果为:
[[ 0.78539826 0.47637034 0.78539826 0.47637034]
[-0.8182709 0.09178917 -0.8182709 0.09178917]]
第二个参数是瓷砖的数量。对于标量,瓷砖是水平铺设的,而不是垂直铺设。它可以是一个表示“铺设”布局的元组
print np.tile(arr12,(2,1))
print np.tile(arr12,(3,2))
结果为:
[[-0.02208397 0.63182887]
[ 2.32495598 -1.45611412]
[-0.02208397 0.63182887]
[ 2.32495598 -1.45611412]]
[[-0.02208397 0.63182887 -0.02208397 0.63182887]
[ 2.32495598 -1.45611412 2.32495598 -1.45611412]
[-0.02208397 0.63182887 -0.02208397 0.63182887]
[ 2.32495598 -1.45611412 2.32495598 -1.45611412]
[-0.02208397 0.63182887 -0.02208397 0.63182887]
[ 2.32495598 -1.45611412 2.32495598 -1.45611412]]
7.花式索引的等价函数:take和put
获取和设置数组子集的一个办法是通过整数数组使用花式索引
arr13=np.arange(10)*100
inds=[7,1,2,6]
print arr13
print arr13[inds]
结果为:
[ 0 100 200 300 400 500 600 700 800 900]
[700 100 200 600]
ndarray有两个方法专门用于获取和设置单个轴向上的选区
print arr13.take(inds)
arr13.put(inds,42)
print arr13
arr13.put(inds,[40,41,42,43])
print arr13
结果为:
[ 0 42 42 300 400 500 42 42 800 900]
[ 0 41 42 300 400 500 43 40 800 900]
要在其他轴上使用take,只需传入axis关键字即可
inds=[2,0,2,1]
arr14=randn(2,4)
print arr14
print arr14.take(inds,axis=1)
结果为:
[[-0.73988407 0.22688772 -0.39941488 -0.0557277 ]
[ 0.35025622 1.37056291 -1.63300772 -0.90342322]]
[[-0.39941488 -0.73988407 -0.39941488 0.22688772]
[-1.63300772 0.35025622 -1.63300772 1.37056291]]
put不接受axis参数,它只会在数组的扁平化版本(一维,C顺序)上进行索引。因此,在需要用其它轴向的索引设置元素时,最好还是使用花式索引
8.广播
广播指的是不同形状的数组之间的算术运算的执行方式
arr15=np.arange(5)
print arr15
print arr15*4
结果为:
[0 1 2 3 4]
[ 0 4 8 12 16]
在这个乘法运算中,标量值4被广播到其它所有的元素上
再来看个,可以通过减去列平均值的方式对数组的每一列进行距平化处理
arr16=randn(4,3)
print arr16
print arr16.mean(0)
demeaned=arr16-arr16.mean(0)
print demeaned
print demeaned.mean(0)
结果为:
[[ 1.05042619 -0.33072072 -0.49485782]
[ 1.1650679 0.81910696 0.71711523]
[ 0.43066235 -0.07393034 0.95870108]
[ 0.98933099 0.28349482 0.65582962]]
[ 0.90887186 0.17448768 0.45919703]
[[ 0.14155433 -0.5052084 -0.95405484]
[ 0.25619604 0.64461928 0.2579182 ]
[-0.47820951 -0.24841802 0.49950405]
[ 0.08045914 0.10900714 0.19663259]]
[ -2.77555756e-17 1.38777878e-17 2.77555756e-17]