Python常用库——numpy
numpy库强大的地方在于科学计算,即矩阵的运算,这部分要求大家具备基本的线性代数运算知识。numpy库部分的知识包括两部分:数组数据类型和数组数据类型的运算。该部分的知识框架如下
1 数组数据类型
1.1 一维数组
首先来了解下数组,数组类型和列表类型非常相似,区别有两个方面,一是同一列表中可以存储多种数据类型(字符串、数字等),而数组只能存储一种数据类型,如果在输入中输入了多种类型,python会将其自动转化成同一数据类型;二是列表不支持不同列表元素之间的四则运算,而数组则支持。虽然大家对于数组可能比较陌生,但应该都接触过矩阵,矩阵是一种特殊的数组。
在python中定义数组也很方便,但是需要在使用前加载numpy库。
import numpy as np a_1 = np.array(["abc","cde"]) a_2 = np.array([1,2,3,4]) a_3 = np.array([0,10,1]) a_4 = np.array([[1,2,3],[4,5,6]]) print(a_1) print(a_2) print(a_3) print(a_4)
运行结果如下:
['abc' 'cde'] [1 2 3 4] [ 0 10 1] [[1 2 3] [4 5 6]]
首先import numpy库,并将其重命名(使用as)为np。进而新建数组,数组的元素可以是字符串、数字等,数组最重要的运算还是对于数字的运算,非数字的更多的使用列表。新建时使用的是np.array(),在括号内使用[]将数组的内容括起来,其元素可以是字符串,可以是数字,也可以是子数组(二维数组可以认为是一维数组的叠加)。
a_f = np.array([1,2,3.3]) a_s = np.array([1,2,3,"ab"]) print(a_f) print(a_s)
数组要求同一数据类型,所以当在数组中给出不同数据类型时,数组会将其自动置为同一数据类型,上述代码中在同一数组中出现了整数和浮点数、整数和字符串,数组分别将其置为浮点数和字符串,运行结果如下:
[1. 2. 3.3] ['1' '2' '3' 'ab']
除使用array进行新建数组外,还可以使用arange函数。arange函数类似于range函数,区别在于range函数只能对整数进行迭代,而arange可以对浮点数进行迭代。arange函数也是包括三个输入变量:开始值,结束值和步长,是一个前闭后开的区间。
print(np.arange(0,1,0.1))
上述代码运行结果如下,从0按照0.1的步长逐步增加到1(不含)。
[0. 0.1 0.2 0.3 0.4 0.5 0.6 0.7 0.8 0.9]
借助arange函数也可以创建新的数组,如下:
a_a = np.arange(0,1,0.2) print(a_a)
输出结果如下:
[0. 0.2 0.4 0.6 0.8]
1.2 二维及高维数组
前面介绍的是一维数组的创建,二维或者更高维度的创建只需要在一维的基础上进行拓展即可,即二维数组的元素是一维数组,三维数组的元素是二维数组,依次类推。关于升维,可以给大家一个直观的例子来理解。线是一维空间(具有长度),面是二维空间(具有面积,是由线构成的面),空间是三维空间(具有长宽高,是一个立体空间)。到三维空间都比较直观,四维空间是在三维的基础上引入时间(同样的,四维空间的元素是三维),一棵树是三维的,一棵树的生长历程是四维的,即四维空间记录了树的发芽生成和衰老。更高维度的空间涉及到更复杂的物理学知识,感兴趣的可以搜索相关的一维到十维空间的讲解。
基于上述不同维度的构成,可以发现一个问题,那就是高维度空间是由低维度组成的。在python中构建高维度数组也是这么做的,二维数组的元素是一维数组,三维数组的元素是二维数组。
a_1_1 = np.array([1,2,3,4])
a_1_2 = np.array([5,6,7,8])
a_2_1 = np.array([a_1_1,a_1_2])
a_2_2 = np.array([[9,10,11,12],[13,14,15,16]])
a_3 = np.array([a_2_1,a_2_2])
print(a_1_1)
print(a_1_2)
print("---")
print(a_2_1)
print(a_2_2)
print("---")
print(a_3)
上面的代码也比较容易理解,定义了两个一维数组,由两个一维数组组合成一个二维数组,由两个二维数组组合成一个三维数组。更高维度的数组构成方法可以持续进行下去。上述代码的输出结果如下:
[1 2 3 4] [5 6 7 8] --- [[1 2 3 4] [5 6 7 8]] [[ 9 10 11 12] [13 14 15 16]] --- [[[ 1 2 3 4] [ 5 6 7 8]] [[ 9 10 11 12] [13 14 15 16]]]
在上面定义的数组中,高维空间都包含多个低维空间元素,如果只包含一个元素,可以通过添加[]建立高维度数组。
print(np.array([[[1,2,3]]]))
上面的输出是一个三维空间,输出结果如下:
[[[1 2 3]]]
除使用[]外,还可以直接在np.array中指定维数。
print(np.array([1,2,3],ndmin = 3))
上述代码中,使用ndmin参数限定为3维数组,输出结果与print(np.array([[[1,2,3]]]))一致。
1.3 特殊数组的构建方法
在科学计算中,有几种常用的矩阵:空矩阵、零矩阵、单位阵。在python中都有对应的简单方法,并且相应的概念可以拓展到数组中。
1.3.1 空矩阵→空数组。
所谓空数组指的是其元素全部为空的数组。在python中使用empty建立。empty有两个输入变量,一个是shape,即输出的维度情况,一维数组只需限定长度即可;二维数组需要限定行数和列数;三维数组则需要限定长宽高三个形状维度;更高维度依次类推。第二个元素是dtype,即元素的数据类型。
#生成一维数组 np.empty(n) #生成二维数组 np.empty((m,n)) #生成三维数组 np.empty(((a,b,c)))
空数组表示相应的元素值为空,但在python中可能并不是空,尤其是在print输出时,对于空数组,建议慎用。
print(np.empty(2)) print(np.empty((2,2)))
输出结果如下,可以发现在print时,有了相应的元素值,无限接近0。
[6.22522714e-321 1.08646184e-311]
[[0. 0.]
[0. 0.]]
1.3.2 零矩阵→零数组
零矩阵,就是元素全部为0的矩阵,在这里拓展为元素全部为0的数组。
print(np.zeros(2))
print("----------")
print(np.zeros((2,3)))
上述代码输出的结果如下:
[0. 0.]
----------
[[0. 0. 0.]
[0. 0. 0.]]
除元素全部为0的数组,还有元素全部为1的数组,使用的np.ones(),参数与np.zeros保持一致。
1.3.3 单位阵
单位矩阵,是指对角线元素全为1,非对角线元素全部为0。单位矩阵只适用于n*n的矩阵,所以在这里没有单位数组的概念。由于单位阵要求行数和列数相同,所以单位阵的输入变量只有一个。
print(np.eye(4))
输出结果如下:
[[1. 0. 0. 0.]
[0. 1. 0. 0.]
[0. 0. 1. 0.]
[0. 0. 0. 1.]]
2 数组的运算
2.1 数组的基本属性
数组的基本属性包括:维度、形状、元素数量、元素数据类型。
2.1.1 维度
维度指的是数组是什么维度的数组,需要区分的是和形状的对比。在python中使用ndim输出对应数组的维度。
a_1 = np.array([1,2,3]) a_2 = np.array([[1,2,3]]) a_3 = np.array([[1,2,3],[4,5,6]]) a_4 = np.array([[[1,2,3],[11,22,33]],[[4,5,6],[44,55,66]]]) print(a_1) print(a_1.ndim) print(a_2) print(a_2.ndim) print(a_3) print(a_3.ndim) print(a_4) print(a_4.ndim)
区分不同维度的方法是看数组是由多少个[]创建的,有几个[]即是几维的数组。上面代码的运行结果是
[1 2 3]
1
[[1 2 3]]
2
[[1 2 3]
[4 5 6]]
2
[[[ 1 2 3]
[11 22 33]]
[[ 4 5 6]
[44 55 66]]]
3
2.1.2 形状
形状是在对应维度下的数组的形状,维度决定了形状的数量。如一维数组只有长度,二维数组有长和宽(对应矩阵的行数和列数),三维数组有长宽高。在python中使用shape输出数组的形状。所以上述四个数组的形状输出如下:
print(a_1.shape) print(a_2.shape) print(a_3.shape) print(a_4.shape)
输出结果如下
(3,) (1, 3) (2, 3) (2, 2, 3)
输出的结果含义是a_1数组的长度是3;a_2数组的行数是1,列数是3;a_3数组的行数是2,列数是3;a_4数组的高是2(包含两个二维数组),其中二维数组的形状又是2行3列的矩阵。
既然数组是有形状的,那就可以改变数组的形状,在python中使用reshape对数组的形状进行变化。需要注意的是,reshape并不会直接变更原变量的形状,需要将变化形状后的值赋给新变量。
a_r = np.array([[1,2,3]]) print(a_r) print(a_r.shape) a_r2= a_r.reshape(3,1) print(a_r2) print(a_r2.shape)
输出结果如下
[[1 2 3]]
(1, 3)
[[1]
[2]
[3]]
(3, 1)
2.1.3 元素数量
元素数量是对数组中的元素进行计数,不考虑维度和形状,在python中使用size进行元素计数。
print(a_1.size) print(a_2.size) print(a_3.size) print(a_4.size)
输出结果即为各个数组包含的元素数
3 3 6 12
2.1.4 元素的数据类型
元素数据类型,数组中要求同一数组中为同一数据类型,当构建数组后,可以使用dtype输出数组的元素数据类型(看变量的数据类型需要使用type)。
print(type(a_1)) print(a_1.dtype)
输出a_1的数据类型是数组,a_1的数据类型是整数型。
<class 'numpy.ndarray'> int32
如果想变化数组中元素数据类型只需要使用astype即可。
a_1.astype(float) print(a_1) a_1_1=a_1.astype(float) print(a_1_1)
输出结果如下
[1 2 3] [1. 2. 3.]
第一次输出a_1,尽管使用了astype,但是并未对改变a_1的数据类型;第二次使用astype时,将输出的结果赋值给变量a_1_1,再次输出a_1_1,此时输出的结果就是变为float数据类型的数组。
2.2 索引
2.2.1 第一层索引
不论是一维数组,还是多维数组,其本质都是一个数组,区别在于一维数组的元素是常见的数字、字符串等,而多维数组的元素是低一个维度数组而已。所以首先介绍的索引可以借鉴列表的索引,也就是start:end:step。在这里介绍一个一维数组和二维数组的例子。
a_i_1 = np.array([1,2,3,4])
a_i_2 = np.array([[1,2,3,4],[5,6,7,8]])
print(a_i_1)
print('\n')
print(a_i_2)
print('\n')
print(a_i_1[0:3:2])
print('\n')
print(a_i_2[0])
print('\n')
print(a_i_2[0:2])
在这里定义了两个数组,a_i_1是一维数组,a_i_2是二维数组,在这里获取的是a_i_1中的元素子集,所以输出的内容还是一维数组,按照索引定义,从0开始,按照步长2开始逐次遍历,直到不超过3,也就是最大是2,所以输出的索引值是0和2,因此输出的结果也就是[1,3]。二维数组,其元素是一维数组,使用简单索引[0],也就是输出二维数组的第一个元素,对应的是一个一维数组[1,2,3,4];第二次使用索引输出的是二维数组的子集,也就是索引值0和1对应的值,此时输出的结果是二维数组的子集,也是一个二维数组。输出结果如下:
[1 2 3 4] [[1 2 3 4] [5 6 7 8]] [1 3] [1 2 3 4] [[1 2 3 4] [5 6 7 8]]
关于这一部分的索引,只要牢记一点,不论多少维度的数组,都可以看做是低一维度的数组的集合,即X维的数组,其元素是X-1维的数组(0维数组即为数字、字符串等元素)。这样在使用索引时就会比较方便了。
如果把上述问题再复杂化一些,所选取的行并不是按照顺序选择(也就是不能直接使用start:end:step)那应该如何选取?方法也比较简单,就是把要选取的行索引值作为一个集合作为输入变量给到数组,则数组可以输出对应的值。在给出这组索引时,需要使用[]括起来,表示这是一组索引。
比方说对于数组a_i_3输出其第1行和第4行,则可以写做
a_i_3 = np.array([[1,2,3,4],[5,6,7,8]]).reshape(4,2)
print(a_i_3)
print("")
print(a_i_3[[0,3]])
输出结果如下:
[[1 2] [3 4] [5 6] [7 8]] [[1 2] [7 8]]
a_i_3是一个4行2列的二维数组,在这里输出的是第1行(索引值0)和第4行(索引值3),也是一个二维数组。
2.2.2 第二层索引
除了上述介绍的索引外,比方说在二维数组中,有了行和列的概念,那应该如何获取相应行和列的元素值,而不是直接输出整个数组。这个地方使用的是数组的嵌套,前面我们提到了X维的数组的元素是X-1维的数组,那自然可以首先获取到X-1维的数组,然后再获取X-1维数组中对应的元素。举个例子
[
[1,2,3]
[4,5,6]
]
上面是定义的一个二维数组,也就是常说的矩阵,矩阵中是有行和列,在这里可以认为第一行是[1,2,3](是一个一维数组),第二行是[4,5,6]。现在想获取第二行第二列的元素值,则只需要array_i[1][1]即可,逻辑比较简单,首先获取数组的第二行,也就是array_i[1],array_i[1]是一维数组[4,5,6],再获取一维数组的第二列元素,所以是array_i[1][1]。
a_i_3 = np.array([[1,2,3],[4,5,6]]) print(a_i_3) print(a_i_3[1][1])
输出结果如下
[[1 2 3] [4 5 6]
剩余60%内容,订阅专栏后可继续查看/也可单篇购买
数据分析入门技术篇
查看29道真题和解析