python基础篇之Numpy

1、numpy是什么

  Python语言一开始并不是设计为科学计算使用的语言,随着越来越多的人发现Python的易用性,逐渐出现了关于Python的大量外部扩展,NumPy (Numeric Python)就是其中之一。NumPy提供了大量的数值编程工具,可以方便地处理向量、矩阵等运算,极大地便利了人们在科学计算方面的工作。另一方面,Python是免费,相比于花费高额的费用使用Matlab,NumPy的出现使Python得到了更多人的青睐。

# 查看numpy的版本
1
import numpy as np 2 np.version.full_version
'1.13.1'

  我们使用了"import"命令导入了NumPy,并使用numpy.version.full_version查出使用的NumPy版本为1.13.1。在后面的介绍中,我们将大量使用NumPy中的函数,每次都添加numpy在函数前作为前缀比较费劲,则我们引入了外部扩展模块时的小技巧,可以使用"from numpy import *"解决这一问题。

  那么问题解决了?慢!Python的外部扩展成千上万,在使用中很可能会import好几个外部扩展模块,如果某个模块包含的属性和方法与另一个模块同名,就必须使用import module来避免名字的冲突。即所谓的名字空间(namespace)混淆了,所以这前缀最好还是带上。

  那有没有简单的办法呢?有的,我们可以在import扩展模块时添加模块在程序中的别名,调用时就不必写成全名了,例如,我们使用"np"作为别名并调用version.full_version函数

2、numpy的对象:数组

  NumPy中的基本对象是同类型的多维数组(homogeneous multidimensional array),这和C++中的数组是一致的,例如字符型和数值型就不可共存于同一个数组中。例如:

# 生成一个步长为1,长度为20的数组
1
a = np.arange(20) 2 print (a)
[ 0  1  2  3  4  5  6  7  8  9 10 11 12 13 14 15 16 17 18 19]

# 查看a类型
1
type(a)
numpy.ndarray

# 重造数组,用reshape函数
1
b = a.reshape(4,5) #将a重造成一个4行5列的二维数组 2 print (b)
[[ 0  1  2  3  4]
 [ 5  6  7  8  9]
 [10 11 12 13 14]
 [15 16 17 18 19]]

# 高维数组
1
c = a.reshape(2,2,5) 2 print (c)
[[[ 0  1  2  3  4]
  [ 5  6  7  8  9]]
 [[10 11 12 13 14]
  [15 16 17 18 19]]]

1 print (c.ndim) #查看维度
2 print (c.shape) #查看各维度的大小
3 print (c.size) #查看全部元素个数
4 print (c.dtype) #查看元素类型
3
(2, 2, 5)
20
int32

 3、创建数组

  数组的创建可通过转换列表实现,高维数组可通过转换嵌套列表实现:

# 一维数组
1
raw1 = [0,1,2,3,4] 2 d = np.array(raw1) 3 print ('d:',d)
# 二维数组
4
raw2 = [[0,1,2,3,4], [5,6,7,8,9]] 5 e = np.array(raw2) 6 print ('e:\n',e)
d: [0 1 2 3 4]
e:
 [[0 1 2 3 4]
 [5 6 7 8 9]]

  一些特殊的数组有特别定制的命令生成,如4*5的全零矩阵:

1 f = (4, 5)
2 np.zeros(f) #创建4行5列的二维数组,元素为0,元素默认是double类型,可以增加参数dtype进行修改
3 g = (4, 5)
4 np.ones(g, dtype=int)#创建4行5列的二维数组,元素为1,元素设定为int类型
array([[ 0.,  0.,  0.,  0.,  0.],
       [ 0.,  0.,  0.,  0.,  0.],
       [ 0.,  0.,  0.,  0.,  0.],
       [ 0.,  0.,  0.,  0.,  0.]])
array([[1, 1, 1, 1, 1],
       [1, 1, 1, 1, 1],
       [1, 1, 1, 1, 1],
       [1, 1, 1, 1, 1]])

  [0, 1)区间的随机数数组:

np.random.rand(5) #产生[0,1)区间的随机数数组
array([ 0.02780353,  0.37508253,  0.15662949,  0.28544584,  0.1020863 ])

4、数组操作之四则运算

  简单的四则运算已经重载过了,全部的’+’,’-’,’*’,’/'运算都是基于全部的数组元素的,以加法为例:

1 a = np.array([[1.0, 2], [2, 4]])
2 print ("a:")
3 print (a)
4 b = np.array([[3.2, 1.5], [2.5, 4]])
5 print ("b:")
6 print (b)
7 print ("a+b:")
8 print (a+b)
a:
[[ 1.  2.]
 [ 2.  4.]]
b:
[[ 3.2  1.5]
 [ 2.5  4. ]]
a+b:
[[ 4.2  3.5]
 [ 4.5  8. ]]

  这里可以发现,a中虽然仅有一个与元素是浮点数,其余均为整数,在处理中Python会自动将整数转换为浮点数(因为数组是同质的),并且,两个二维数组相加要求各维度大小相同。当然,NumPy里这些运算符也可以对标量和数组操作,结果是数组的全部元素对应这个标量进行运算,还是一个数组:

1 print ("3 * a:")
2 print (3 * a)
3 print ("b + 1.8:")
4 print (b + 1.8)
3 * a:
[[  3.   6.]
 [  6.  12.]]
b + 1.8:
[[ 5.   3.3]
 [ 4.3  5.8]]

  类似C++,’+=’、’-=’、’*=’、’/='操作符在NumPy中同样支持:

1 a /= 2
2 print (a)
[[ 0.5  1. ]
 [ 1.   2. ]] 

  开根号求指数也很容易:

1 print ("np.exp(a):")
2 print (np.exp(a)) #指数
3 print ("np.sqrt(a):")
4 print (np.sqrt(a)) #开方
5 print ("np.square(a):")
6 print (np.square(a)) #平方
7 print ("np.power(a, 3):")
8 print (np.power(a, 3)) #三次方
np.exp(a):
[[  2.71828183   7.3890561 ]
 [  7.3890561   54.59815003]]
np.sqrt(a):
[[ 1.          1.41421356]
 [ 1.41421356  2.        ]]
np.square(a):
[[  1.   4.]
 [  4.  16.]]
np.power(a, 3):
[[  1.   8.]
 [  8.  64.]]

  需要知道二维数组的最大最小值怎么办?想计算全部元素的和、按行求和、按列求和怎么办?for循环吗?不,NumPy的ndarray类已经做好函数了:

1 i = np.arange(20).reshape(4,5)
2 print ("i:")
3 print (i)
4 print ("sum of all elements in i: " + str(i.sum())) #求和
5 print ("maximum element in i: " + str(i.max())) #最大值
6 print ("minimum element in i: " + str(i.min())) #最小值
7 print ("maximum element in each row of i: " + str(i.max(axis=1))) #每行的最大值
8 print ("minimum element in each column of i: " + str(i.min(axis=0))) #每列的最小值
i:
[[ 0  1  2  3  4]
 [ 5  6  7  8  9]
 [10 11 12 13 14]
 [15 16 17 18 19]]
sum of all elements in i: 190
maximum element in i: 19
minimum element in i: 0
maximum element in each row of i: [ 4  9 14 19]
minimum element in each column of i: [0 1 2 3 4]

  科学计算中大量使用到矩阵运算,除了数组,NumPy同时提供了矩阵对象(matrix)。矩阵对象和数组的主要有两点差别:一是矩阵是二维的,而数组的可以是任意正整数维;二是矩阵的’*‘操作符进行的是矩阵乘法,乘号左侧的矩阵列和乘号右侧的矩阵行要相等,而在数组中’*'操作符进行的是每一元素的对应相乘,乘号两侧的数组每一维大小需要一致。数组可以通过asmatrix或者mat转换为矩阵,或者直接生成也可以:

1 j = np.arange(20).reshape(4,5) #二维数组
2 j = np.asmatrix(j) #转化成矩阵
3 print (type(j))
4 print (j)
5 
6 k = np.matrix('1.0 2.0; 3.0 4.0') #创建矩阵
7 print (type(k))
8 print (k)
<class 'numpy.matrixlib.defmatrix.matrix'>
[[ 0  1  2  3  4]
 [ 5  6  7  8  9]
 [10 11 12 13 14]
 [15 16 17 18 19]]
<class 'numpy.matrixlib.defmatrix.matrix'>
[[ 1.  2.]
 [ 3.  4.]]

  再来看一下矩阵的乘法,这使用arange生成另一个矩阵b,arange函数还可以通过arange(起始,终止,步长)的方式调用生成等差数列,注意含头不含尾。

1 k = np.arange(2,45,3).reshape(3,5) #arange指的是步长,表示在2到45之间每3各取一个数
2 k = np.mat(k)
3 print (type(k))
4 print (k)
<class 'numpy.matrixlib.defmatrix.matrix'>
[[ 2  5  8 11 14]
 [17 20 23 26 29]
 [32 35 38 41 44]]

  有人要问了,arange指定的是步长,如果想指定生成的一维数组的长度怎么办?好办,"linspace"就可以做到:

1 l = np.linspace(0,1,9) # linspace表示在0到1之间一共取9个数
2 print (l)
3 m = l.reshape(3,3)
4 m = np.asmatrix(m)
5 print (type(m))
6 print (m)
[ 0.     0.125  0.25   0.375  0.5    0.625  0.75   0.875  1.   ]
<class 'numpy.matrixlib.defmatrix.matrix'>
[[ 0.     0.125  0.25 ]
 [ 0.375  0.5    0.625]
 [ 0.75   0.875  1.   ]]

5、数组元素访问

   数组和矩阵元素的访问可通过下标进行,以下均以二维数组(或矩阵)为例:

1 m = np.array([[1.0,2],[3.0,5]])
2 print (m)
3 print (m[0][1]) #访问格式1
4 print (m[0,1]) #访问格式2
[[ 1.  2.]
 [ 3.  5.]]
2.0
2.0
 1 # 赋值实例
 2 o = m #这样赋值后对m进行重新赋值,发现o也发生了变化,这是因为Python不是真正将m复制一份给o,而是将o指到了m对应数据的内存地址上,
 3 m[0,1] = 999
 4 print ('m:')
 5 print (m)
 6 print ('o:')
 7 print (o) 
 8 print ()
 9 print ("*******************")
10 print ()
11 p = m.copy() #若要想赋值,并且不想出现上述情形,可以用copy函数来完成
12 m[0,1] = 111
13 print ('m:')
14 print (m)
15 print ('p:')
16 print (p)
m:
[[   1.  999.]
 [   3.    5.]]
o:
[[   1.  999.]
 [   3.    5.]]
*******************
m:
[[   1.  111.]
 [   3.    5.]]
p:
[[   1.  999.]
 [   3.    5.]]

  访问某一列或者某一行的数据,用“:”符号。

 1 q = np.arange(20).reshape(4,5)
 2 print (q)
 3 print ()
 4 print ("the 1st and 3rd column of q:")
 5 print (q[:,(1,3)])
 6 print ()
 7 print ("the 2nd row of q:")
 8 print (q[2,:])
 9 print ()
10 print ("将第一列大于5的元素(10和15)对应的第三列元素(12和17)取出来:")#更复杂情形
11 print (q[:,2][q[:,0]>5])
[[ 0  1  2  3  4]
 [ 5  6  7  8  9]
 [10 11 12 13 14]
 [15 16 17 18 19]]

the 1st and 3rd column of q:
[[ 1  3]
 [ 6  8]
 [11 13]
 [16 18]]

the 2nd row of q:
[10 11 12 13 14]

将第一列大于5的元素(10和15)对应的第三列元素(12和17)取出来:
[12 17]

  可使用where函数查找特定值在数组中的位置:
1 r = np.where(q ==18)
2 print (r)
(array([3], dtype=int64), array([3], dtype=int64))

6、数组操作之矩阵

  还是拿矩阵(或二维数组)作为例子:

 # 矩阵的转置
1
s = np.random.rand(3,4) #创建3行4列的二维数组 2 print (s) 3 print ("数组的转置:") 4 s_t = np.transpose(s) 5 print (s_t) 6 print ("**************************") 7 t = np.mat(s) #转换成矩阵类型 8 print (type(t)) 9 print (t) 10 print ("矩阵的转置:") 11 print (t.T)
[[ 0.63939104  0.4267525   0.711497    0.23821614]
 [ 0.78402388  0.16975021  0.63667862  0.70169351]
 [ 0.46436988  0.76405254  0.46564003  0.94176015]]
数组的转置:
[[ 0.63939104  0.78402388  0.46436988]
 [ 0.4267525   0.16975021  0.76405254]
 [ 0.711497    0.63667862  0.46564003]
 [ 0.23821614  0.70169351  0.94176015]]
**************************
<class 'numpy.matrixlib.defmatrix.matrix'>
[[ 0.63939104  0.4267525   0.711497    0.23821614]
 [ 0.78402388  0.16975021  0.63667862  0.70169351]
 [ 0.46436988  0.76405254  0.46564003  0.94176015]]
矩阵的转置:
[[ 0.63939104  0.78402388  0.46436988]
 [ 0.4267525   0.16975021  0.76405254]
 [ 0.711497    0.63667862  0.46564003]
 [ 0.23821614  0.70169351  0.94176015]]
 # 矩阵的求逆
1
import numpy.linalg as nlg 2 u = np.random.rand(2,2) 3 u = np.mat(u) 4 print ("u:") 5 print (u) 6 u_1 = nlg.inv(u) 7 print ("u_1:") 8 print (u_1) 9 print () 10 print ("乘积为单位矩阵来验证:") 11 print (u * u_1)
u:
[[ 0.75373943  0.53785259]
 [ 0.31554461  0.21885755]]
u_1:
[[ -46.02762626  113.11502707]
 [  66.36174467 -158.5178845 ]]

乘积为单位矩阵来验证:
[[  1.00000000e+00   0.00000000e+00]
 [ -1.77635684e-15   1.00000000e+00]]
# 求特征值和特征向量
1
v = np.random.rand(3,3) 2 eig_value,eig_vector = nlg.eig(v) 3 print ("eig_value:") 4 print (eig_value) 5 print ("eig_vector:") 6 print (eig_vector)
eig_value:
[ 1.00780791+0.j         -0.20549578+0.18720574j -0.20549578-0.18720574j]
eig_vector:
[[ 0.40202136+0.j         -0.37400209+0.38405454j -0.37400209-0.38405454j]
 [ 0.70752764+0.j         -0.00198203-0.36678799j -0.00198203+0.36678799j]
 [ 0.58119142+0.j          0.76032046+0.j          0.76032046-0.j        ]]
 # 按列拼接
1
w = np.array([1,2,3]) 2 x = np.array([4,5,6]) 3 print (np.column_stack((w,x))) 4 print () 5 # 还可以用hstack或者vstack来拼接 6 y = np.random.rand(2,2) 7 z = np.random.rand(2,2) 8 print ("y:") 9 print (y) 10 print ("z:") 11 print (z) 12 a = np.hstack([y,z]) 13 b = np.vstack([y,z]) 14 print ("a:") 15 print (a) 16 print ("b:") 17 print (b)
[[1 4]
 [2 5]
 [3 6]]

y:
[[ 0.46717864  0.99926719]
 [ 0.29806068  0.26909811]]
z:
[[ 0.30794373  0.80832404]
 [ 0.56473473  0.07050252]]
a:
[[ 0.46717864  0.99926719  0.30794373  0.80832404]
 [ 0.29806068  0.26909811  0.56473473  0.07050252]]
b:
[[ 0.46717864  0.99926719]
 [ 0.29806068  0.26909811]
 [ 0.30794373  0.80832404]
 [ 0.56473473  0.07050252]]

7、缺失值

   缺失值在分析中也是信息的一种,NumPy提供nan作为缺失值的记录,通过isnan判定。
1 c = np.random.rand(2,2)
2 c[0, 1] = np.nan
3 print (np.isnan(c))
4 print (np.nan_to_num(c)) #nan_to_num可用来将nan替换成0
[[False  True]
 [False False]]
[[ 0.71645542  0.        ]
 [ 0.59114199  0.19739796]]

 

posted @ 2018-02-26 14:40  Calex  阅读(419)  评论(0编辑  收藏  举报