python学习笔记--Numpy模块(一)

发布时间:2023-11-03 16:00

目录

  • 传送门
  • Numpy的介绍
    • Numpy是什么?
    • Numpy特点
    • Numpy安装
  • Numpy的基本操作
    • 创建数组
    • Numpy数据类型
      • 数据类型
      • 指定数组数据类型
  • 数组的维度
    • 查看数组的维度
    • 查看数组的形状
    • 创建二维数组
    • 创建三维数组
    • 重塑数组
      • 一维转多维
      • 多维转一维
      • 转置
      • 换轴
    • 创建数组的其他函数
  • 数组的算术
    • 数组与标量的算术操作
    • 两个等尺寸数组的算术操作
    • 广播机制

传送门

Numpy模块(二)

Numpy的介绍

Numpy是什么?

Numpy(Numerical Python)是目前Python数值计算中最为重要的基础包。大多数计算包都提供了基于Numpy的科学函数功能,将Numpy的数组对象作为数据交换的通用语。

Numpy特点

  • 提供高效多维数组
  • 提供了基于数组的便捷算术操作以及广播机制
  • 对数据进行快速的矩阵计算
  • 对硬盘中数组数据进行读写操作

Numpy安装

pip install numpy

Numpy的基本操作

创建数组

  1. 可以将列表转换为数组
import numpy as np


li = [1,2,3,4]
i = np.array(li)
print(i)
  1. 生成数组
import numpy as np


i = np.arange(1,10,2)
  • arange的使用方法range()函数类似,参数的意思基本也一样。
  • 不管用哪种方式创建数组,它的数据类型都是numpy.ndarray

Numpy数据类型

注意,ndarray数组里面的每个元素均为相同类型.
例如下面这个列表,列表中有整数也有浮点数,然后转换为ndarray数组

li = [1,3.3,3,4.4]
i = np.array(li)
print(i)

输出结果:整个数组的数字都转为浮点数了

array([1. , 3.3, 3. , 4.4])

然后可以用dtype输出它的数据类型

print(i.dtype)

输出结果是:

float64

数据类型

类型 类型代码 描述
int8,uint8 i1,u1 有符号和无符号的8数位整数
int16,uint16 i2,u2 有符号和无符号的16数位整数
int32,uint32 i4,u4 有符号和无符号的32数位整数
int64,uint64 i8,u8 有符号和无符号的64数位整数
float16 f2 半精度浮点数
float32 f4 标准单精度浮点数
float64 f8 标准双精度浮点数
bool ? 布尔值,存储True或False
string_ S ASCII字符串类型,eg:‘S10’
unicode_ U Unicode类型,eg:‘U10’

指定数组数据类型

在创建数组时,不管是array()还是arange()方法都有一个dtype参数,使用这个参数就可以指定数组的数据类型

li = [1,False,3,4.4]
i = np.array(li, dtype=np.int64)
print(i.dtype)

也可以通过类型代码实现:

li = [1,False,3,4.4]
i = np.array(li, dtype=\"i2\")
print(i.dtype)

如果数据类型指定为布尔值的话,那么它实际就是将每个元素都进行一次布尔值运算

li = [1,2,3,4.4,0,-2,-3]
i = np.array(li, dtype=np.bool)
print(i)
# 输出结果:[ True  True  True  True False  True  True]

已经创建好的数组,还可以用到astype()方法改变数据类型

  • 注意,由于astype()方法不会修改对象本身,因此需要有个变量接收它
li = [1,2,3,4.4,0,-2,-3]
i = np.array(li, dtype=np.bool)
i = i.astype(np.int32)
print(i.dtype)

数组的维度

查看数组的维度

使用ndim方法可以查看数组的维度

li = [1,2,3,4.4,0,-2,-3]
i = np.array(li, dtype=np.bool)
i.ndim

查看数组的形状

使用shape方法可以查看数组的形状

li = [1,2,3,4.4,0,-2,-3]
i = np.array(li, dtype=np.bool)
i.shape
# 返回结果: (7,)
  • 返回结果是元组的形式
  • 由于现在只是1维,因此元组里面只有一个元素,元组里面的7代表这个数组有7个元素。

创建二维数组

\"python学习笔记--Numpy模块(一)_第1张图片\"

创建二维数组其实也是使用array(),但是传入的列表格式为 “[[],[]]”,一个方括号包着两个方括号

li = [1,2,3,]
li2 = [4,5,6]
i = np.array([li,li2])
print(i)
print(\"数组的形状:\",i.shape)
print(\"数组的维度:\",i.ndim)

#返回结果
[[1 2 3]
 [4 5 6]]
数组的形状: (2, 3)
数组的维度: 2
  • 从返回结果可以看出,这是一个2维的2行3列的数组

当两个列表不对称时,是无法构建出2维数组
比如下面的例子:

li = [1,2,3,]
li2 = [4,5]
i = np.array([li,li2])
print(i)
print(\"数组的形状:\",i.shape)
print(\"数组的维度:\",i.ndim)

# 返回结果
[list([1, 2, 3]) list([4, 5])]
数组的形状: (2,)
数组的维度: 1
  • 最后构建得出的只是2个1维的数组

创建三维数组

\"python学习笔记--Numpy模块(一)_第2张图片\"
创建三维的方式和二维的类似,但是二维只需要行、列即可构成,三维则还需要加上一个“坨”,每一坨代表一个二维数组。
代码中的格式如下:

i = np.array([[[1, 2, 3], [4, 5, 6]], [[7, 8, 9], [10, 11, 12]]])
print(i)
print(\"数组的形状:\",i.shape)
print(\"数组的维度:\",i.ndim)

# 返回结果
[[[ 1  2  3]
  [ 4  5  6]]

 [[ 7  8  9]
  [10 11 12]]]
数组的形状: (2, 2, 3)
数组的维度: 3
  • 返回结果,这是个3维的数组,数组中有2坨二维数组,每坨二维数组是2行3列。

与二维同理,如果每坨二维数组是不对称的,那么也是无法构建出三维数组

i = np.array([[[1, 2, 3], [4, 5, 6]], [[7, 8, 9, 10], [10, 11, 12, 13]]])
print(i)
print(\"数组的形状:\",i.shape)
print(\"数组的维度:\",i.ndim)

# 返回结果
[[list([1, 2, 3]) list([4, 5, 6])]
 [list([7, 8, 9, 10]) list([10, 11, 12, 13])]]
数组的形状: (2, 2)
数组的维度: 2

重塑数组

一维转多维

使用reshape()方法可以重塑数组。
从源码中可以看出,它传入的参数为shape,也就是要传入数组的形状。
\"python学习笔记--Numpy模块(一)_第3张图片\"

arr = np.arange(6)  # 生成一个一维数组
arr2 = arr.reshape(2,3)  # 将1维转为2维
print(arr2)
print(\"数组的形状:\",arr2.shape)
print(\"数组的维度:\",arr2.ndim)

# 返回结果
[[0 1 2]
 [3 4 5]]
数组的形状: (2, 3)
数组的维度: 2


arr3 = arr.reshape(1,2,3) # 将1维转3维
print(arr3) 
print(\"数组的形状:\",arr3.shape)
print(\"数组的维度:\",arr3.ndim)

# 返回结果
arr3 = arr.reshape(1,2,3) # 将1维转3维
print(arr3) 
print(\"数组的形状:\",arr3.shape)
print(\"数组的维度:\",arr3.ndim)
  • 由于reshape()方法并不会修改对象本身,因此需要有个变量去接收它

在源码中可以发现,reshape()方法还有一个order=\'C’的默认参数,尝试下改为order=‘F’,再看看结果

arr = np.arange(6)  # 生成一个一维数组
arr2 = arr.reshape(2, 3, order=\"F\")  # 将1维转为2维
print(arr2)
print(\"数组的形状:\", arr2.shape)
print(\"数组的维度:\", arr2.ndim)

# 返回结果
[[0 2 4]
 [1 3 5]]
数组的形状: (2, 3)
数组的维度: 2


arr3 = arr.reshape(1, 2, 3, order=\"F\") # 将1维转3维
print(arr3) 
print(\"数组的形状:\", arr3.shape)
print(\"数组的维度:\", arr3.ndim)

# 返回结果
[[[0 2 4]
  [1 3 5]]]
数组的形状: (1, 2, 3)
数组的维度: 3

返回结果好像没有太大区别,再将两种结果拿出来对比:

# order=\"F\"返回结果
[[0 2 4]
 [1 3 5]]
数组的形状: (2, 3)
数组的维度: 2

# order=\"C\"返回结果
[[0 1 2]
 [3 4 5]]
数组的形状: (2, 3)
数组的维度: 2
  • 仔细看的话可以发现,order=\"C\"时,重塑数组时是从行方向开始构建; 但如果order=\"F\"时, 重塑数组时由列方向开始构建。

在重塑三维的时候,“坨、行、列”这三个要素中有其中一个要素你不想算的时候,可以用-1代替,但只能代替1个数
例如下面的代码,我的数组总共有24个元素,我生成2坨、3行,但不知道几列,因此列的参数我可以放个-1代替。

arr4 = np.arange(24).reshape(2,3,-1)
print(arr4) 
print(\"数组的形状:\", arr4.shape)
print(\"数组的维度:\", arr4.ndim)

# 返回结果
[[[ 0  1  2  3]
  [ 4  5  6  7]
  [ 8  9 10 11]]

 [[12 13 14 15]
  [16 17 18 19]
  [20 21 22 23]]]
数组的形状: (2, 3, 4)
数组的维度: 3

多维转一维

基于目前学到的知识,用reshape()也可以实现多维转一维.
下面的例子是三维转一维

arr4 = np.arange(24).reshape(-1,3,4)  # 目前arr4是一个三维数组

arr5 = arr4.reshape(arr4.shape[0]*arr4.shape[1]*arr4.shape[2])  # 三维转一维
print(arr5) 
print(\"数组的形状:\", arr5.shape)
print(\"数组的维度:\", arr5.ndim)
  • 其实这个思路很简单,由于三维是由“坨数、行数、列数”组成的,因此只要将这三者全部相乘,得出的就是一维数组的元素的个数;然后因为一维数组的形状是(X, ),而X就=元素的个数,所以上面的代码就相当于是
arr5 = arr4.reshape(2*3*4)
# 等于
arr5 = arr4.reshape(24,)

不过多维转一维的方法肯定不止这一种,还有更加简便的方法,使用flatten()和ravel()

arr5.flatten()
arr5.ravel()

# 返回结果
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])

转置

转置是沿着对角线将行与列对换.
使用transpose()和T都可以实现转置

arr6 = np.arange(10).reshape(2,5)
arr6.transpose()
# arr6.T 

# 返回结果
array([[0, 5],
       [1, 6],
       [2, 7],
       [3, 8],
       [4, 9]])

换轴

换轴就是将行与列对换

arr6 = np.arange(10).reshape(2,5)
arr6.swapaxes(1, 0)

# 返回结果
array([[0, 5],
       [1, 6],
       [2, 7],
       [3, 8],
       [4, 9]])
  • 这样看上去,转置和换轴其实没啥区别,其实所谓换轴也是转置的一种
    具体区别可参考知乎大佬的文章 链接: swapaxes和transpose的区别

创建数组的其他函数

函数名 描述
array 将输入数据转换为ndarray数组,自动推断数据类型,默认复制所有输入数据
asarray 将输入数据转换为ndarray数组,但输入数据已经是ndarray则不再复制
arange python内建函数range的数组版,返回一个数组
zeros 根据给定形状和数据类型生成全0数组
ones 根据给定形状和数据类型生成全1数组
empty 根据给定形状和数据类型生成一个没有初始化数值的空数组
full 根据给定形状和数据类型生成指定数值的数组

array和asarray的区别

data = np.arange(6)
arr1 = np.array(data)  # 浅拷贝
arr2 = np.asarray(data)  # 深拷贝

data[2] = 9  # 将第三个数值改为9
print(data)  # 改变了
print(arr1)  # 没变
print(arr2)  # 改变了\\

# 返回结果:
[0 1 9 3 4 5]
[0 1 2 3 4 5]
[0 1 9 3 4 5]
  • array和asarray的区别在于一个是拷贝值,一个是拷贝内存地址,因此当data发生改变array不会跟着变,而asarray会跟着一起变。类似于浅拷贝和深拷贝。
  • asarray会作为深拷贝的前提是data是一个ndarray数组,如果data只是个列表,那还是属于浅拷贝。

zeros、ones、empty、full的使用

arr1 = np.zeros((2,3))  # zeros
print(arr1)

# 返回结果
[[0. 0. 0.]
 [0. 0. 0.]]

arr2 = np.ones((2,3))
print(arr2)

# 返回结果
[[1. 1. 1.]
 [1. 1. 1.]]

arr3 = np.empty((2,3))
print(arr3)

# 返回结果
[[1. 1. 1.]
 [1. 1. 1.]]

arr4 = np.full((2,3),3)
print(arr4)

#返回结果
[[3 3 3]
 [3 3 3]]
  • empty的返回结果是没有经过初始化的数组,因此上面的代码看上去返回的都是1,但是调整一下形状,返回的可能就是另外的数了。
  • zeros、ones、empty默认的数据类型都是float类型, 而full默认是None
  • 另外zeros、ones、empty、full都有另一种方法,那就是在后面加上_like
zeros_like
ones_like
empty_like
full_like
  • 他们的使用方法都一样,传入一个已经存在的数组,会根据这个数组的形状去生成数组,生成怎样的数组那就是根据他们原有功能来决定了。

数组的算术

数组与标量的算术操作

数组与标量的算术操作会把计算参数传递给数组的每一个元素。

arr1 = np.arange(6).reshape(2,3)
print(arr1)
print(arr1+1)

# 返回结果
[[0 1 2]
 [3 4 5]]
[[1 2 3]
 [4 5 6]]

arr1 = np.arange(6).reshape(2,3)
print(arr1)
print(arr1*3)

#返回结果
[[0 1 2]
 [3 4 5]]
[[ 0  3  6]
 [ 9 12 15]]
  • 可以发现这些两个算式都是一样,数组的每个元素都进行了+1或者*3,这就是数组与标量的算术操作

两个等尺寸数组的算术操作

两个等尺寸数组的算术操作实际上是逐元素操作。

arr2 = np.arange(6).reshape(2,3)
arr3 = np.arange(6).reshape(2,3)

arr2 + arr3

# 返回结果
[[0 1 2]
 [3 4 5]]
[[0 1 2]
 [3 4 5]]
[[ 0  2  4]
 [ 6  8 10]]
  • 两个相等形状的数组除了做计算,也能做比较运算,运算结果返回布尔值类型的数组。

广播机制

广播机制规则:如果对于每个结尾维度(即从尾部开始的),轴长度都匹配或者长度都是1,两个二维数组就是可以进行广播的。之后,广播会在丢失的或者长度为1的轴上进行。

数组维度不同,结尾轴长度一致
\"python学习笔记--Numpy模块(一)_第4张图片\"

  • 在其丢失的轴上进行,也就是0轴广播,或者叫行轴广播
    代码如下:
arr4 = np.arange(12).reshape(4,3)  # 四行三列
arr5 = np.arange(3)                # 一行三列 也就是行数不等,列数相等

arr6 = arr4 - arr5
print(arr6)

# 返回结果
[[0 0 0]
 [3 3 3]
 [6 6 6]
 [9 9 9]]

数组维度相同,其中有个轴长度为1
\"python学习笔记--Numpy模块(一)_第5张图片\"

  • 在其长度为1轴上进行,此处也就是1轴广播,或者叫列轴广播
    代码如下
arr7 = np.arange(12).reshape(4,3)  # 四行三列
arr8 = np.arange(4).reshape(4,1)  # 四行一列, 列相等,行不等

arr9 = arr7 - arr8
print(arr9)

# 返回结果
[[0 1 2]
 [2 3 4]
 [4 5 6]
 [6 7 8]]
  • 维度完全不一致,也就是行列都不一致的,无法广播。

ItVuer - 免责声明 - 关于我们 - 联系我们

本网站信息来源于互联网,如有侵权请联系:561261067@qq.com

桂ICP备16001015号