python3疯狂之路

Python数据分析(一)--numpy全知全会

2018-12-15  本文已影响0人  周且南_laygin

这是python在数据分析和机器学习系列文章的第一篇。
本文全面阐述numpy的方方面面,以供参考。
numpy不仅是数据分析的基础包,也是机器学习进行科学计算的基础。

一、写在前面

导入包

import numpy
#通常的做法是指定一个别名
#下面例子任何地方使用到的np若无特殊说明,一律都是指numpy
import numpy as np 
#当然也可以这样导入全部,但是强烈建议不要这样做
from numpy import *

基础属性

numpy的主要对象是多维数组,既然是数组,就必要要有相同的数据类型,同时也可以进行各种计算和操作。关于基础概念,下面以一个例子来详细说明

例子

>>> import numpy as np
>>> n1 = np.array([1,2,3,4],np.int)  #一维数组
>>> n1
array([1, 2, 3, 4])
>>> type(n1)
<class 'numpy.ndarray'>
>>> n1.shape  #形状,1行4列
(4,)
>>> n1.ndim  #维度,这是一维
1
>>> n1.size  #元素个数
4
>>> n1.dtype  #元素的数据类型
dtype('int32')
>>> n1.itemsize  #每个元素的字节大小
4
#为了更好说明以上的属性,以一个多维数组为例就很明显了
>>> n2 = np.arange(24).reshape(3,2,4)    #三维数组,arange函数生成的元素值为0到23
>>> n2
array([[[ 0,  1,  2,  3],
        [ 4,  5,  6,  7]],

       [[ 8,  9, 10, 11],
        [12, 13, 14, 15]],

       [[16, 17, 18, 19],
        [20, 21, 22, 23]]])
>>> n2.shape 
(3, 2, 4)
>>> n2.ndim
3
>>> n2.dtype
dtype('int32')
>>> n2.size
24

array的创建

通过上面的例子,numpy数组可由常规的List进行创建。此外,numpy也提供了创建特定数组的函数。

例子

>>> n3 = np.zeros([2,3])   #zeros创建全零数组,可指定长度
>>> n3
array([[ 0.,  0.,  0.],
       [ 0.,  0.,  0.]])
>>> n301 = np.ones([2,3]) #同zeros,ones创建全为1的数组
>>> n301
array([[ 1.,  1.,  1.],
       [ 1.,  1.,  1.]])    
>>> n302 = np.empty((3,3))  #empty创建的数组元素值随机分配,与内存状态有关
>>> n302
array([[  1.19563886e-321,   0.00000000e+000,   0.00000000e+000],
       [  0.00000000e+000,   0.00000000e+000,   1.08694442e-321],
       [  0.00000000e+000,   0.00000000e+000,   0.00000000e+000]])
#此外,还有zeros_like、ones_like、empty_like函数,参数为一个数组,
#创建出形状与给定数组相同的全零、全一或随机值的数组。
#以zeros_like为例
>>> n4 = np.arange(12).reshape(3,4)
>>> n4
array([[ 0,  1,  2,  3],
       [ 4,  5,  6,  7],
       [ 8,  9, 10, 11]])
>>> np.zeros_like(n4)   #形状与n4相同的全零数组
array([[0, 0, 0, 0],
       [0, 0, 0, 0],
       [0, 0, 0, 0]])
>>> a = np.arange(1,3,0.5)  #指定范围和步长,生成一维数组
>>> a
array([ 1. ,  1.5,  2. ,  2.5])       
>>> np.linspace(1,3,5)  #指定范围和元素个数
array([ 1. ,  1.5,  2. ,  2.5,  3. ])  
#随机数组,random中还有诸如randn、random之类的随机函数可生成数组  
>>> np.random.rand(3,2)  
array([[ 0.27133972,  0.73467037],
       [ 0.41100736,  0.75078034],
       [ 0.12516107,  0.98181898]])            

array的操作

例子

# 首先看看数组的切片,以三维数组为例
>>> n5 = np.arange(24).reshape(3,2,4)
>>> n5
array([[[ 0,  1,  2,  3],
        [ 4,  5,  6,  7]],

       [[ 8,  9, 10, 11],
        [12, 13, 14, 15]],

       [[16, 17, 18, 19],
        [20, 21, 22, 23]]])
#获取某个特定的值,可以这样
>>> n5[1,1,1]
13
>>> n5[n5%2==0]    #选出数组中的偶数
array([ 0,  2,  4,  6,  8, 10, 12, 14, 16, 18, 20, 22])
>>> i = [0,0,1,1,1]
>>> j = [1,1,0,0,0]
>>> k = [1,1,0,0,1]
>>> n5[i,j,k]   #i,j,k需要有相同的长度
array([5, 5, 8, 8, 9])
>>> n5[:,:,:]      #全切片,只要理解了这种切分方式,就很好理解取得各个维度的数据该怎么写了
array([[[ 0,  1,  2,  3],
        [ 4,  5,  6,  7]],

       [[ 8,  9, 10, 11],
        [12, 13, 14, 15]],

       [[16, 17, 18, 19],
        [20, 21, 22, 23]]])
>>> n5[:,:,1:2]     #筛选出第三个维度的第二个数据。注意,第一二维是全部数据
array([[[ 1],
        [ 5]],

       [[ 9],
        [13]],

       [[17],
        [21]]])        
#数组的维度变换,对于上面的三维数组。
>>>n5.reshape(4,6)  #转换成四行六列的二维数组,创建一个副本,n5本身没有变
array([[ 0,  1,  2,  3,  4,  5],
       [ 6,  7,  8,  9, 10, 11],
       [12, 13, 14, 15, 16, 17],
       [18, 19, 20, 21, 22, 23]])    
>>> n5.shape = 4,6     #改变了数组本身的形状
>>> n5
array([[ 0,  1,  2,  3,  4,  5],
       [ 6,  7,  8,  9, 10, 11],
       [12, 13, 14, 15, 16, 17],
       [18, 19, 20, 21, 22, 23]])          
>>> n5.shape =3,2,-1     
>>> n5.shape
(3, 2, 4)  
#把一个数组切分为多个较小的数组
>>> n6
array([[ 0,  1,  2,  3],
       [ 4,  5,  6,  7],
       [ 8,  9, 10, 11]])
>>> np.hsplit(n6,2)  #相当于把数组切成水平方向的两个小数组
[array([[0, 1],
       [4, 5],
       [8, 9]]), array([[ 2,  3],
       [ 6,  7],
       [10, 11]])]  
>>> np.hsplit(n6,(1,3))   #指定列前后切
[array([[0],
       [4],
       [8]]), array([[ 1,  2],
       [ 5,  6],
       [ 9, 10]]), array([[ 3],
       [ 7],
       [11]])]       
>>> np.vsplit(n6,3)
[array([[0, 1, 2, 3]]), array([[4, 5, 6, 7]]), array([[ 8,  9, 10, 11]])]       
#数组堆积操作。对如下两个2*3的二维数组
>>> a = np.arange(6).reshape(2,3)
>>> b = np.linspace(6,12,6).reshape(2,3)
>>> a
array([[0, 1, 2],
       [3, 4, 5]])
>>> b
array([[  6. ,   7.2,   8.4],
       [  9.6,  10.8,  12. ]])
>>> np.vstack((a,b))   #按照行来堆积,可理解为垂直排
array([[  0. ,   1. ,   2. ],
       [  3. ,   4. ,   5. ],
       [  6. ,   7.2,   8.4],
       [  9.6,  10.8,  12. ]])
>>> np.hstack((a,b))  #按照列来堆积,可理解为水平方向并排一起
array([[  0. ,   1. ,   2. ,   6. ,   7.2,   8.4],
       [  3. ,   4. ,   5. ,   9.6,  10.8,  12. ]])   
#关于数组的拷贝
>>> c = np.arange(2,9)
#d和c是完全相同的数组,存储位置一样
>>> d=c    
>>> d is c
True 
#e是c的浅拷贝,有相同的元素,一个修改另一个也被修改,但存储的位置不一样  
>>> e = c.view()
>>> e
array([2, 3, 4, 5, 6, 7, 8])
>>> e[0] = 333
>>> c
array([333,   3,   4,   5,   6,   7,   8])
>>> e
array([333,   3,   4,   5,   6,   7,   8])
>>> e is c
False 
#f是c的深拷贝,修改值相互不影响
>>> f = c.copy()
>>> f
array([333,   3,   4,   5,   6,   7,   8])
>>> f[0]=2
>>> c
array([333,   3,   4,   5,   6,   7,   8]) 

二、向量和矩阵

numpy在向量和矩阵的运算中扮演着十分重要的角色,不仅提供许多常用的数学和统计函数,并且计算速度也很不错。

基础运算

numpy数组的算术运算是基于元素级别的,并且基于numpy的广播机制,在数据运算中,若维度不一致也能进行运算。numpy支持的算术运算很多,就不一一列举了。

例子

>>> a
array([[1, 2, 3, 4],
       [2, 3, 4, 3]])
>>> b
array([[0, 1, 2, 3],
       [4, 5, 6, 7]])
>>> c
array([5, 6, 4, 7])
>>> a+b   #元素对应相加
array([[ 1,  3,  5,  7],
       [ 6,  8, 10, 10]])
>>> a+c  #即使c只有一维,也会广播到a的每一维进行计算
array([[ 6,  8,  7, 11],
       [ 7,  9,  8, 10]])

向量与矩阵的运算

标量、向量与矩阵之间相互的运算,在numpy中实现起来十分简单,比如常见的点积(內积)、外积和叉乘。下面以两个矩阵a、b和两个向量c、d展示一下numpy在这些运算中的实现。

例子

>>> a                #2*4的矩阵
array([[1, 2, 3, 4],
       [2, 3, 4, 3]])
>>> b                 #2*4的矩阵
array([[0, 1, 2, 3],
       [4, 5, 6, 7]])
>>> c                 #向量
array([5, 6, 4, 7])
>>> d = np.arange(2,6)
>>> d                  #向量
array([2, 3, 4, 5])
>>> np.dot(c,d)       #向量的內积是个标量
79
>>> np.dot(a,b.T)     #矩阵的点积,这里将b转置成4*2的矩阵(若使用np.inner便不需要将b转置)
array([[20, 60],
       [20, 68]])
>>> np.dot(a,c)   #矩阵和向量的点积
array([57, 65])       
>>> np.outer(c,d)             #向量的外积
array([[10, 15, 20, 25],
       [12, 18, 24, 30],
       [ 8, 12, 16, 20],
       [14, 21, 28, 35]])
>>> np.outer(a,b)            #矩阵的外积
array([[ 0,  1,  2,  3,  4,  5,  6,  7],
       [ 0,  2,  4,  6,  8, 10, 12, 14],
       [ 0,  3,  6,  9, 12, 15, 18, 21],
       [ 0,  4,  8, 12, 16, 20, 24, 28],
       [ 0,  2,  4,  6,  8, 10, 12, 14],
       [ 0,  3,  6,  9, 12, 15, 18, 21],
       [ 0,  4,  8, 12, 16, 20, 24, 28],

对于矩阵,np.linalg中提供了矩阵的各种运算包括转置、矩阵求逆等等。

例子 矩阵操作

#矩阵的转置,直接在矩阵后面接个.T,如上的矩阵b
>>> b.T     #与 b.transpose()是等价的
array([[0, 4],
       [1, 5],
       [2, 6],
       [3, 7]])
#同时也可以对多维数组进行转置操作
>>> np.arange(12).reshape(2,2,3)
array([[[ 0,  1,  2],
        [ 3,  4,  5]],

       [[ 6,  7,  8],
        [ 9, 10, 11]]])
>>> np.arange(12).reshape(2,2,3).T  #2*2*3变成了3*2*2
array([[[ 0,  6],
        [ 3,  9]],

       [[ 1,  7],
        [ 4, 10]],

       [[ 2,  8],
        [ 5, 11]]])     
#为了便于计算,给定一个方阵i

>>> i = np.arange(9).reshape(3,3)
>>> i
array([[0, 1, 2],
       [3, 4, 5],
       [6, 7, 8]])
>>> np.trace(i)  #矩阵的迹,即对角线上元素之和
12   
#使用 np.linalg 的eig计算出矩阵的特征值和特征向量
>>> t1,tv = np.linalg.eig(i)
>>> t1      #特征值
array([  1.33484692e+01,  -1.34846923e+00,  -2.48477279e-16])
>>> tv      #特征向量
array([[ 0.16476382,  0.79969966,  0.40824829],
       [ 0.50577448,  0.10420579, -0.81649658],
       [ 0.84678513, -0.59128809,  0.40824829]])   
#上面挖了个坑,这里构造一个可逆的矩阵j
>>> j = np.array([[3,1,4],[3,3,5],[1,7,1]])
>>> j
array([[3, 1, 4],
       [3, 3, 5],
       [1, 7, 1]])
>>> np.linalg.det(j)    #求矩阵的行列式
-22.000000000000004
>>> np.linalg.inv(j)   #求矩阵的逆矩阵
array([[ 1.45454545, -1.22727273,  0.31818182],
       [-0.09090909,  0.04545455,  0.13636364],
       [-0.81818182,  0.90909091, -0.27272727]]) 
#对一个3*4的矩阵进行奇异值分解       
>>> u,s,v = np.linalg.svd(np.arange(12).reshape(3,4)) 
>>> u
array([[-0.1473065 , -0.90090739,  0.40824829],
       [-0.50027528, -0.2881978 , -0.81649658],
       [-0.85324407,  0.32451178,  0.40824829]])
>>> s
array([  2.24092982e+01,   1.95534034e+00,   7.68985043e-16])
>>> v
array([[-0.39390139, -0.46087474, -0.5278481 , -0.59482145],
       [ 0.73813393,  0.29596363, -0.14620666, -0.58837696],
       [-0.50775138,  0.52390687,  0.47544042, -0.4915959 ],
       [-0.20539847,  0.65232016, -0.68844492,  0.24152322]])

除此之外,linalg模块中还有许多操作,如:

 - norm            Vector or matrix norm
- inv             Inverse of a square matrix
- solve           Solve a linear system of equations
- det             Determinant of a square matrix
- lstsq           Solve linear least-squares problem
- pinv            Pseudo-inverse (Moore-Penrose) calculated using a singular
                  value decomposition
- eig             Eigenvalues and vectors of a square matrix
- eigh            Eigenvalues and eigenvectors of a Hermitian matrix
- eigvals         Eigenvalues of a square matrix
- eigvalsh        Eigenvalues of a Hermitian matrix
- qr              QR decomposition of a matrix
- svd             Singular value decomposition of a matrix
- cholesky        Cholesky decomposition of a matrix
- tensorsolve     Solve a linear tensor equation
- tensorinv       Calculate an inverse of a tensor

三、常用数学函数

numpy中包括丰富的数学函数和统计函数,比如三角函数、统计学上的均值、方差、标准差、相关系数等。

基本数学函数

如常见的求和、最小/最大值等(对于多维数组,可指定对哪个轴进行计算)。下面以三维数组n5求和为例说明一下关于轴的选择。

例子

>>> n5           #这是一个3*2*4的数组
array([[[ 0,  1,  2,  3],
        [ 4,  5,  6,  7]],

       [[ 8,  9, 10, 11],
        [12, 13, 14, 15]],

       [[16, 17, 18, 19],
        [20, 21, 22, 23]]])
#对第一个轴求和,即相当于对第一维(长度为3)进行计算,得到的是2*4的数组
#24=0+8+16,以此类推        
>>> np.sum(n5,axis=0)   
array([[24, 27, 30, 33],
       [36, 39, 42, 45]])
#对第二个轴求和,即相当于对第二维(长度为2)进行计算,得到的是3*4的数组
#4=0+4,以此类推       
>>> np.sum(n5,axis=1)
array([[ 4,  6,  8, 10],
       [20, 22, 24, 26],
       [36, 38, 40, 42]])
#对第三个轴求和,即相当于对第三维(长度为4)进行计算,得到的是3*2的数组
#6=0+1+2+3,以此类推       
>>> np.sum(n5,axis=2)
array([[ 6, 22],
       [38, 54],
       [70, 86]])
>>> np.sum(n5)  #所有元素的和
276       

三角函数

在numpy中使用三角函数也很方便,比如正弦np.sin;相应的,余弦:cos,正切:tan,以及反函数arcsin、arccos和arctan。还有一些诸如双曲函数,sinh、cosh、tanh等等。

例子

>>> np.sin(np.pi/2)   #计算pi的正弦值为1
1.0
#计算并画出0到2*pi的正弦函数曲线
>>> e = np.arange(0,2*np.pi,0.1)
>>> import matplotlib.pyplot as plt
>>> plt.plot(e,np.sin(e))
[<matplotlib.lines.Line2D object at 0x0000000004D54C18>]
>>> plt.show()   #结果如图

[图片上传失败...(image-1d6edc-1544870342615)]

统计函数

比较常见的有均值(mean)、标准差(std)、方差(var)、中位数(median)、协方差(cov)、相关系数(corrcoef)等。同样对于多维数组,也可以指定根据哪个轴进行计算。

>>> n5
array([[[ 0,  1,  2,  3],
        [ 4,  5,  6,  7]],

       [[ 8,  9, 10, 11],
        [12, 13, 14, 15]],

       [[16, 17, 18, 19],
        [20, 21, 22, 23]]])
>>> np.std(n5)
6.9221865524317288
>>> np.std(n5,axis=0)
array([[ 6.53197265,  6.53197265,  6.53197265,  6.53197265],
       [ 6.53197265,  6.53197265,  6.53197265,  6.53197265]])

小例子

使用numpy计算一个sigmoid函数的值并画出函数图像。
f\left(x\right)=\frac{1}{1+e^{-x}}

>>> def sigmoid(x):
...     return 1.0/(1+np.e**(-x))
...
>>> x = np.arange(-5,5,0.01)
>>> plt.plot(x,sigmoid(x))
[<matplotlib.lines.Line2D object at 0x0000000008287AC8>]
>>> plt.show()  #如图
sigmoid函数

结语

以上就是笔者工作中常用到的功能,特此记录下来,便于以后查阅,如果能够帮到需要的人再好不过了。虽然希望也尽力能够全方位解析numpy在数据分析和科学计算上面的魅力,怎奈时间精力和个人知识经验有限,实在不可能面面俱到,如果有欠缺的地方还望参考其他更多资料,如果能够留言给予提醒那就再感激不过了。

上一篇 下一篇

猜你喜欢

热点阅读