Numpy是Python一个很重要的第三方库,用于科学计算。
注:以下代码均在jupyter qtconsole中实现,导入了%pylab
环境。
生成数据
linspace
linspace用来生成一组等间隔的数据
In [51]: %pylab # 启用pylab模式,直接导入了很多科学计算库。
In [52]: a = linspace(0, 2*pi, 21)
In [53]: a
Out[53]:
array([ 0. , 0.31415927, 0.62831853, 0.9424778 , 1.25663706,
1.57079633, 1.88495559, 2.19911486, 2.51327412, 2.82743339,
3.14159265, 3.45575192, 3.76991118, 4.08407045, 4.39822972,
4.71238898, 5.02654825, 5.34070751, 5.65486678, 5.96902604,
6.28318531])
In [54]: %precision 3 # 在qtconsole中设置数据显示精度为小数点后3位。若直接使用%precision即可恢复默认精度。
Out[54]: '%.3f'
In [55]: a
Out[55]:
array([ 0. , 0.314, 0.628, 0.942, 1.257, 1.571, 1.885, 2.199,
2.513, 2.827, 3.142, 3.456, 3.77 , 4.084, 4.398, 4.712,
5.027, 5.341, 5.655, 5.969, 6.283])
ogrid
ogrid方法产生一系列等差数据,类似于Matlab的start:step:stop。示例如下:
In [27]: x = ogrid[0:10]
In [28]: x
Out[28]: array([0, 1, 2, 3, 4, 5, 6, 7, 8, 9])
In [29]: x = ogrid[0:10:2]
In [30]: x
Out[30]: array([0, 2, 4, 6, 8])
# 小技巧:若产生的数组要包含末尾的数,可以使用虚数符号"j"加以实现。
In [32]: x
Out[32]: array([ 0., 1., 2., 3., 4., 5., 6., 7., 8., 9., 10.])
In [33]: x = ogrid[0:10:6j]
In [34]: x
Out[34]: array([ 0., 2., 4., 6., 8., 10.])
# 还可以直接产生二维数据
In [35]: x, y = ogrid[0:10:2, 10:20:6j]
In [36]: x
Out[36]:
array([[ 0.],
[ 2.],
[ 4.],
[ 6.],
[ 8.]])
In [37]: y
Out[37]: array([[ 10., 12., 14., 16., 18., 20.]])
另外,r_,c_分别产生行向量数据与列向量数据,使用方法与此类似。
快捷方式产生矩阵
ones,zeros,empty,identity等分别产生1矩阵,0矩阵,空矩阵(0矩阵),单位矩阵(对角线为1)
显示命名空间参数
使用who()
或者whos
即可显示当前命名空间参数,如:
In [92]: who()
Name Shape Bytes Type
===========================================================
size 200 1600 float64
a 21 168 float64
b 21 168 float64
_25 (b) 21 168 float64
_29 (b) 21 168 float64
_30 21 21 bool
x 50 400 float64
_45 200 1600 float64
y 50 400 float64
_48 200 1600 float64
_50 (_45) 200 1600 float64
_51 (_48) 200 1600 float64
_53 (size) 200 1600 float64
color 200 1600 float64
t 50 400 float64
Upper bound on total bytes = 7957
In [93]: whos
Variable Type Data/Info
-------------------------------
a ndarray 21: 21 elems, type `float64`, 168 bytes
b ndarray 21: 21 elems, type `float64`, 168 bytes
color ndarray 200: 200 elems, type `float64`, 1600 bytes
size ndarray 200: 200 elems, type `float64`, 1600 bytes
t ndarray 50: 50 elems, type `float64`, 400 bytes
x ndarray 50: 50 elems, type `float64`, 400 bytes
y ndarray 50: 50 elems, type `float64`, 400 bytes
数组属性
建立了数组a,则它的常用属性如下:
In [162]: a = array([[1, 2, 3], [4, 5, 6]])
In [163]: a
Out[163]:
array([[1, 2, 3],
[4, 5, 6]])
1.查看类型
In [164]: type(a)
Out[164]: numpy.ndarray
2.查看数组中的数据类型
In [165]: a.dtype
Out[165]: dtype('int64')
3.查看数组中每个元素所占字节
In [166]: a.itemsize
Out[166]: 8
4.查看数组的行列数
In [167]: a.shape
Out[167]: (2, 3) # 说明是2行3列的数组
5.查看数组元素数目
In [168]: a.size
Out[168]: 6 # 数组元素数目等于行数与列数的乘积
6.查看数组所占空间
In [169]: a.nbytes
Out[169]: 48 # 数组所占空间为数组的itemize与size的乘积
7.查看数组维数
In [170]: a.ndim
Out[170]: 2 # 表明是二维数组
fill填充数据
fill方法将数组设置为指定值。如:
In [180]: a
Out[180]:
array([[1, 2, 3],
[4, 5, 6]])
In [181]: a.fill(-4.8)
In [182]: a
Out[182]:
array([[-4, -4, -4],
[-4, -4, -4]])
注意,此时a保持行列数不变,元素全部变成了-4。但是为什么不是-4.8呢?那是因为此时数组a的dtype为int,所以只能保留为整数。可做如下更改:
In [183]: a.dtype
Out[183]: dtype('int64')
In [184]: a.dtype = 'float'
In [185]: a.dtype
Out[185]: dtype('float64')
In [186]: a.fill(-4.8)
In [187]: a
Out[187]:
array([[-4.8, -4.8, -4.8],
[-4.8, -4.8, -4.8]])
可以看到,此时a中所有元素变成了-4.8。
任意类型的数组
numpy中的数组默认为同一类型,可以是数值型,也可以是字符串型,但不能是混合型。但是,当使用dtype=object
时,即可创建任意类型的数组。如:
In [398]: a = array([1, 1.2, 'hello', [10, 20, 30]], dtype=object)
In [399]: a
Out[399]: array([1, 1.2, 'hello', [10, 20, 30]], dtype=object)
In [400]: a.itemsize
Out[400]: 8
In [402]: a.dtype
Out[402]: dtype('O')
In [403]: a * 2
Out[403]: array([2, 2.4, 'hellohello', [10, 20, 30, 10, 20, 30]], dtype=object)
数据引用
切片引用
现有原数组a,切片引用产生了数组b,修改b中的元素会影响a中的元素。如:
In [248]: a = array([0, 1, 2, 3, 4])
In [249]: a
Out[249]: array([0, 1, 2, 3, 4])
In [252]: b = a[2:4]
In [253]: b
Out[253]: array([2, 3])
In [254]: b[0] = 999
In [255]: b
Out[255]: array([999, 3])
In [256]: a
Out[256]: array([ 0, 1, 999, 3, 4])
说明在numpy数组中,python并没有为b分配新的内存空间,而是让b指向了a分配的内存空间。因此,改变b会改变a的值。
python默认的列表就不存在此现象,如:
In [257]: a = [0, 1, 2, 3, 4]
In [258]: b = a[2:4]
In [259]: b
Out[259]: [2, 3]
In [260]: b[0] = 999
In [261]: b
Out[261]: [999, 3]
In [262]: a
Out[262]: [0, 1, 2, 3, 4]
若要在numpy的数组中,改变b不影响a的值,可以使用copy()
实现,如:
In [271]: a = array([0, 1, 2, 3, 4])
In [272]: b = a[2:4].copy()
In [275]: b[0] = 999
In [276]: b
Out[276]: array([999, 3])
In [277]: a
Out[277]: array([0, 1, 2, 3, 4])
数组方法
sum求和
In [8]: a
Out[8]:
array([[1, 2, 3],
[4, 5, 6]])
In [9]: sum(a)
Out[9]: 21
In [12]: a.sum()
Out[12]: 21
沿着指定维度求和
In [10]: sum(a, axis=0) # 沿着行的维度求和
Out[10]: array([5, 7, 9])
In [11]: sum(a, axis=1) # 沿着列的维度求和
Out[11]: array([ 6, 15])
In [14]: a.sum(axis=0) # 沿着第一维求和
Out[14]: array([5, 7, 9])
In [16]: a.sum(axis=1) # 沿着第二维求和
Out[16]: array([ 6, 15])
prod求积
使用方法同sum
此外,max,min,mean, std,var等方法与sum方法的使用也差不多。
clip
将数值限制在某个范围
In [66]: a
Out[66]:
array([[1, 2, 3],
[4, 5, 6]])
In [67]: a.clip(3, 5) # a中小于3的数变成3,大于5的数变成5
Out[67]:
array([[3, 3, 3],
[4, 5, 5]])
In [68]: a
Out[68]:
array([[1, 2, 3],
[4, 5, 6]])
ptp
计算数组中最大值与最小值的差
In [68]: a
Out[68]:
array([[1, 2, 3],
[4, 5, 6]])
In [69]: a.ptp()
Out[69]: 5
In [70]: a.ptp(axis=0)
Out[70]: array([3, 3, 3])
In [71]: a.ptp(axis=1)
Out[71]: array([2, 2])
round
四舍五入,0.5的近似规则为近似到偶数值。
In [78]: b = rand(10)*10
In [79]: b
Out[79]:
array([ 2.57598829, 7.69588774, 9.79707955, 7.10994638, 5.27285863,
6.50838994, 9.39987486, 4.00583049, 2.58985365, 5.69761458])
In [80]: b.round()
Out[80]: array([ 3., 8., 10., 7., 5., 7., 9., 4., 3., 6.])
In [81]: b.round(decimals=1) # 保留1位小数的近似
Out[81]: array([ 2.6, 7.7, 9.8, 7.1, 5.3, 6.5, 9.4, 4. , 2.6, 5.7])
从一列数据中抽出某个区间的数据
假设有0到100之间的100个随机数,如何找出40到60之间的数据?
In [163]: a = floor(rand(100) * 100)
In [164]: a
Out[164]:
array([ 4., 10., 6., 33., 77., 43., 19., 74., 43., 24., 70.,
97., 25., 55., 2., 26., 21., 79., 71., 66., 9., 2.,
75., 96., 27., 32., 0., 6., 3., 24., 92., 24., 94.,
38., 34., 67., 81., 94., 55., 16., 22., 88., 76., 53.,
30., 35., 13., 7., 70., 63., 25., 29., 91., 62., 57.,
86., 77., 41., 68., 52., 1., 18., 94., 20., 60., 86.,
80., 57., 13., 87., 8., 12., 86., 75., 6., 54., 84.,
36., 34., 56., 37., 55., 85., 22., 18., 95., 8., 91.,
50., 25., 94., 60., 20., 18., 49., 18., 37., 97., 33.,
67.])
方法之一是使用searchsorted函数实现。searchsorted有两个参数,第一个参数是一列一维数组,第二个参数是一系列值,返回值相当于保持第一个数组的排序性质不变,将第二个数组中的值插入第一个数组中的位置。看示例:
In [183]: a.sort() # 对a进行从小到大排序
In [184]: a
Out[184]:
array([ 0., 1., 2., 2., 3., 4., 6., 6., 6., 7., 8.,
8., 9., 10., 12., 13., 13., 16., 18., 18., 18., 18.,
19., 20., 20., 21., 22., 22., 24., 24., 24., 25., 25.,
25., 26., 27., 29., 30., 32., 33., 33., 34., 34., 35.,
36., 37., 37., 38., 41., 43., 43., 49., 50., 52., 53.,
54., 55., 55., 55., 56., 57., 57., 60., 60., 62., 63.,
66., 67., 67., 68., 70., 70., 71., 74., 75., 75., 76.,
77., 77., 79., 80., 81., 84., 85., 86., 86., 86., 87.,
88., 91., 91., 92., 94., 94., 94., 94., 95., 96., 97.,
97.])
In [185]: bounds = 40, 60 # 设定边界,下边界为40,上边界为60
In [186]: low_idx, high_idx = searchsorted(a, bounds) #使用searchsorted函数
In [187]: low_idx # 获取a中下边界40对应的数组下标
Out[187]: 48
In [188]: high_idx # 获取a中上边界60对应的数组下标
Out[188]: 62
In [189]: a[low_idx]
Out[189]: 41.0
In [190]: a[high_idx]
Out[190]: 60.0
In [191]: a[low_idx:high_idx] # 取得a中40到60之间的数
Out[191]:
array([ 41., 43., 43., 49., 50., 52., 53., 54., 55., 55., 55.,
56., 57., 57.])
连接数组
使用concatenate,vstack,hstack等方法。
In [2]: x = array([[0, 1, 2], [10, 11, 12]])
In [3]: y = array([[50, 51, 52], [60, 61, 62]])
In [4]: z = concatenate((x, y)) # 沿着第一维度进行连接
In [5]: z
Out[5]:
array([[ 0, 1, 2],
[10, 11, 12],
[50, 51, 52],
[60, 61, 62]])
In [6]: vstack((x, y))
Out[6]:
array([[ 0, 1, 2],
[10, 11, 12],
[50, 51, 52],
[60, 61, 62]])
In [7]: concatenate((x, y), axis=1) # 沿着第二维度进行连接
Out[7]:
array([[ 0, 1, 2, 50, 51, 52],
[10, 11, 12, 60, 61, 62]])
In [8]: hstack((x, y))
Out[8]:
array([[ 0, 1, 2, 50, 51, 52],
[10, 11, 12, 60, 61, 62]])
扁平化数组
flatten,flat,方法将多维数组降为1维
In [10]: z
Out[10]:
array([[ 0, 1, 2],
[10, 11, 12],
[50, 51, 52],
[60, 61, 62]])
In [12]: z.flatten()
Out[12]: array([ 0, 1, 2, 10, 11, 12, 50, 51, 52, 60, 61, 62])
In [20]: z # 说明flatten()不影响原数组
Out[20]:
array([[ 0, 1, 2],
[10, 11, 12],
[50, 51, 52],
[60, 61, 62]])
In [22]: z.flat[:] # 使用flat方法也能实现
Out[22]: array([ 0, 1, 2, 10, 11, 12, 50, 51, 52, 60, 61, 62])
In [23]: z.flat # 此时返回一个迭代器
Out[23]: <numpy.flatiter at 0x7fa602180a00>
In [24]: list(z.flat)
Out[24]: [0, 1, 2, 10, 11, 12, 50, 51, 52, 60, 61, 62]
In [25]: z.ravel()
Out[25]: array([ 0, 1, 2, 10, 11, 12, 50, 51, 52, 60, 61, 62])
In [26]: z # ravel方法不影响原数组
Out[26]:
array([[ 0, 1, 2],
[10, 11, 12],
[50, 51, 52],
[60, 61, 62]])
astype
astype实现数据类型转换
In [77]: a = ones([5, 4])
In [78]: a
Out[78]:
array([[ 1., 1., 1., 1.],
[ 1., 1., 1., 1.],
[ 1., 1., 1., 1.],
[ 1., 1., 1., 1.],
[ 1., 1., 1., 1.]])
In [79]: a.astype(int)
Out[79]:
array([[1, 1, 1, 1],
[1, 1, 1, 1],
[1, 1, 1, 1],
[1, 1, 1, 1],
[1, 1, 1, 1]])
In [80]: a
Out[80]:
array([[ 1., 1., 1., 1.],
[ 1., 1., 1., 1.],
[ 1., 1., 1., 1.],
[ 1., 1., 1., 1.],
[ 1., 1., 1., 1.]])
In [81]: a.dtype
Out[81]: dtype('float64')
# 不能直接改变dtype进行类型转换
In [82]: a.dtype = 'int'
In [83]: a
Out[83]:
array([[4607182418800017408, 4607182418800017408, 4607182418800017408,
4607182418800017408],
[4607182418800017408, 4607182418800017408, 4607182418800017408,
4607182418800017408],
[4607182418800017408, 4607182418800017408, 4607182418800017408,
4607182418800017408],
[4607182418800017408, 4607182418800017408, 4607182418800017408,
4607182418800017408],
[4607182418800017408, 4607182418800017408, 4607182418800017408,
4607182418800017408]])