Python常用库——numpy

numpy库强大的地方在于科学计算,即矩阵的运算,这部分要求大家具备基本的线性代数运算知识。numpy库部分的知识包括两部分:数组数据类型和数组数据类型的运算。该部分的知识框架如下
r'ZZZZZZZ'

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%内容,订阅专栏后可继续查看/也可单篇购买

数据分析入门技术篇

全部评论

相关推荐

评论
点赞
1
分享

创作者周榜

更多
牛客网
牛客网在线编程
牛客网题解
牛客企业服务