Numpy模块的学习(上)

一、前期准备

1. 简介

  • Numpy(Numerical Python),由多维数组对象用于处理这些数组的例程集合组成的库。
  • 可执行对数组的数学和逻辑运算;用于形状操纵的傅里叶变换和例程;可用于线性代数操作;有线性代数和随机数生成的内置函数。
  • 由Numeric和Numarray整合而成。
  • 常于Scipy(Scientific Python)和matplotlib(绘图库)一起使用,三者组合可在一定程度上替代MatLab。

2. 安装

直接在有Python环境的终端下运行命令:

pip install numpy
# 或者是
pip install --user numpy  # 出现拒绝访问的错误时就用该命令安装

测试numpy是否安装成功:

python

import numpy   # 导入numpy库
numpy.eye(4)     # 生成对角矩阵

在这里插入图片描述

二、具体学习

1. ndarray对象

  • ndarray(The N-dimensional array),是一系列同类型数据的多维数组,以0为下标开始在集合中进行元素索引。每个元素在内存中都有相同存储大小的区域。
  • ndarray 对象由计算机内存的连续一维部分组成,并结合索引模式,将每个元素映射到内存块中的一个位置。内存块以行顺序(C样式)或列顺序(FORTRAN或MatLab风格,即前述的F样式)来保存元素。
  • ndarray的内部由以下内容组成:
    • 一个指向数据(内存或内存映射文件中的一块数据)的指针。
    • 描述在数组中的固定大小值的格子,即数据类型(dtype)。
    • 一个表示数组形状(shape)的元组,表示各维度大小。
    • 一个跨度元组(stride),其中的整数指的是为了前进到当前维度下一个元素需要“跨过”的字节数。

1. ndarray的内部结构

在这里插入图片描述
跨度可以是负数,这样会使数组在内存中后向移动,例如切片中的obj[::-1]。

2. array()方法创建ndarray对象

array()方法的基本语法:

numpy.array(object,
	dtype=None, 
	copy=True, 
	order=None, 
	subok=False, 
	ndmin=0)

array()方法的参数说明

参数 说明
object 必选参数,类型为array_like。可以是四种类型数据:(1)数组;(2)公开数组接口的任何对象;(3)__array__()方法返回数组的对象;(4)任何(嵌套)序列。np.array()的作用就是按照一定要求将object转换为数组。
dtype 可选参数,用来表示数组元素的类型。如果没有给出,那么类型将被确定为序列中的对象所需的最小类型。注意:此参数只能用于“向上转换”数组,对于降级,需要使用.astype(t)方法。
copy 可选参数,类型为bool。默认为True,表示复制对象。否则只在三种情况下才返回复制的副本:(1)如果__array__返回的是一个副本;(2)如果object是一个嵌套序列;(3)如果需要一个副本来满足其他参数要求(dtype、order等参数)。
order 可选参数,指定阵列的内存布局。C为行方向,F为列方向,A为任意方向(默认)。
subok 可选参数,类型为bool,默认为False,返回一个与基类一致的数组。值为True,表示子类将被传递,即使用object的内部数据类型;否则返回的数组将被强制为基类,即使用object数组的数据类型。
ndmin 可选参数,类型为int。指定生成数组的最小维数。

array()方法的示例

  1. 简单创建一维ndarray:
import numpy as np

a = np.array([1, 2, 3])
print(a)

# 输出:[1 2 3]
  1. 创建二维ndarray:
import numpy as np

a = np.array([[1, 2], [3, 4]])
print(a)

''' 输出:
[[1 2]
 [3 4]]
'''
  1. 使用ndmin参数设置维度:
import numpy as np

a = np.array([1, 2, 3], ndmin=2)
print(a)

# 输出:[[1 2 3]]
  1. 使用dtype参数设置数组元素的数据类型:
import numpy as np

a = np.array([1, 2, 3], dtype=complex)
print(a)

# 输出:[1.+0.j 2.+0.j 3.+0.j]

2. 数据类型

  • numpy支持比Python更多种类的数据类型。

1. Numpy的不同标量数据类型表

数据类型 描述
bool_ 存储为字节的布尔值(True 或 False)
int_ 默认整数类型,通常为int64或int32(与C语言的long相同)
intc 通常为int32或int64(与C语言中的int相同)
intp 用于索引的整数,通常为int32或int64(与C语言中的ssize_t相同)
int8 字节(-128~127)
int16 整数(-32768~32767)
int32 整数(-2147483648~2147483647)
int64 整数(-9223372036854775808~9223372036854775807)
uint8 无符号整数(0~255)
uint16 无符号整数(0~65535)
uint32 无符号整数(0~4294967295)
uint64 无符号整数(0~18446744073709551615)
float_ float64类型的简写
float16 半精度浮点数,包括:1个符号位,5个指数位,10个尾数位
float32 单精度浮点数,包括:1个符号位,8个指数位,23个尾数位
float64 双精度浮点数,包括:1个符号位,11个指数位,52个尾数位
complex_ complex128类型的简写,即128位复数
complex64 复数,表示双32位浮点数(实数部分和虚数部分)
complex128 复数,表示双64浮点数(实数部分和虚数部分)

2. 内建类型对应的字符代码

字符 对应类型
b 布尔类型
i (有符号)整型
u 无符号整型integer
f 浮点型
c 复数浮点型
m timedelta(时间间隔)
M datetime(日期时间)
O (Python)对象
S,a (byte-)字符串
U Unicode
V 原始数据(void)

3. 数据类型对象(dtype)

  • 数据类型对象(numpy.dtype 类的实例)用来描述与数组对应的内存区域是如何使用的。

1. dtype()的基本语法

numpy.dtype(object, align, copy)

2. dtype()方法的参数说明

参数 说明
object 要转换为的数据类型对象
align 默认为False。如果为True,填充字段使其类似C语言的结构体
copy 复制对象,默认为True。如果为False,则是对内置数据类型对象的引用。

3. dtype()方法的示例

  1. 使用常规的标量类型:
import numpy as np

# 使用标量类型
dt = np.stype(np.int32)

# 输出:int32
  1. 使用标量类型的缩写:
import numpy as np

# int8、int16、int32、int64四种数据类型可以使用字符串‘i1’,‘i2’,‘i4’,‘i8’代替(其中1、2、3、4、8代表字节,一个字节有8位。)
dt = np.dtype('i4')
print(dt)

# 输出:int32
  1. 使用字节顺序标注:
    • 数据的字节顺序:小端法(<)指的是最小值存储在最小的地址,即低位组放在最前面。大端法(>)指的是最重要的字节存储在最小的地址,即高位组放在最前面。
import numpy as np

# 字节顺序标注
dt = np.dtype('<i4')    # 小端法
print(dt)

# 输出:int32

下面示例是结构化数据类型的使用,类型字段和对应的实际类型将被创建。

  1. 首先创建结构化数据类型:
import numpy as np

# 首先创建结构化数据类型
dt = np.dtype([('age', np.int8)])
print(dt)

# 输出:[('age', 'i1')]
  1. 将数据类型应用于ndarray对象:
import numpy as np

# 结构化数据类型
dt = np.dtype([('age', np.int8)])
# 将数据类型应用于ndarray对象
a = np.array([(10,), (20,), (30,)], dtype=dt)
print(a)

# 输出:[(10,) (20,) (30,)]
  1. 类型字段名可用于存取实际的age列:
import numpy as np

dt = np.dtype([('age', np.int8)])
a = np.array([(10, ), (20, ), (30, )], dtype=dt)
# 通过类型字段名读取指定列
print(a['age'])

# 输出:[10 20 30]

下面示例定义一个结构化数据类型student,包含字符串字段name,整数字段age,浮点数字段marks,并将这个dtype应用到ndarray对象。

  1. 结构化数据类型student:
import numpy as np

# 结构化数据类型student
dt = np.dtype([('name', 'S20'), ('age', 'i1'), ('marks', 'f4')])
print(dt)

# 输出:[('name', 'S20'), ('age', 'i1'), ('marks', '<f4')]
  1. 将数据类型student应用在ndarray上:
import numpy as np

# 结构化数据类型student
student = np.dtype([('name', 'S20'), ('age', 'i1'), ('marks', 'f4')])
a = np.array([('Tom', 20, 78), ('Marry', 23, 88), ('Lucky', 23, 89)], dtype=student)
print(a['age'])
print(a['name'])
print(a['marks'])
print(a)

'''运行结果:
[20 23 23]
[b'Tom' b'Marry' b'Lucky']
[78. 88. 89.]
[(b'Tom', 20, 78.) (b'Marry', 23, 88.) (b'Lucky', 23, 89.)]
'''

3. 数组属性

  • Numpy的数组称为(rank),秩就是轴的数量,即维度,一维数组的秩为1。
  • 在Numpy中,每一个线性的数组称为一个轴(axis),也就是维度(dimensions)。第一个轴是底层数组,第2个轴是底层数组里的数组。
  • 可以声明axis=0,表示沿着第0轴进行操作,即对每一列进行操作axis=1,表示沿着第1轴进行操作,即对每一行进行操作

Numpy数组中比较重要的ndarray对象属性

属性 说明
ndarray.ndim 秩,即轴的数量或维度的数量。
ndarray.shape 数组的维度,对于矩阵,n行m列。
ndarray.size 数组元素的总个数,相当于.shape中n*m的值。
ndarray.dtype ndarray对象的元素类型。
ndarray.itemsize ndarray对象中每个元素的大小(以字节为单位)。
ndarray.flags ndarray对象的内存信息。
ndarray.real ndarray元素的实部。
ndarray.imag ndarray元素的虚部。
ndarray.data 包含实际数组元素的缓冲区,由于一般通过数组的索引获取元素,所以通常不需要使用这个属性。

1. ndarray.ndim

  • 用于返回数组的维度,等于秩。
import numpy as np

a = np.arange(24)
print(a.ndim)       # a 只有一个维度
print(a)
# 调整大小
b = a.reshape(2, 4, 3)    # b 现在拥有三个维度
print(b.ndim)
print(b)
a[-1] = 100   # a和b也是相互影响的,改变对方的值,双方都会改变
b[0] = 99
print(a)
print(b)
print(id(a))    # 2274023823184
print(id(b))    # 2274023823664
'''运行结果:
1
[ 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
[[[ 0  1  2]
  [ 3  4  5]
  [ 6  7  8]
  [ 9 10 11]]

 [[12 13 14]
  [15 16 17]
  [18 19 20]
  [21 22 23]]]
[ 99  99  99  99  99  99  99  99  99  99  99  99  12  13  14  15  16  17
  18  19  20  21  22 100]
[[[ 99  99  99]
  [ 99  99  99]
  [ 99  99  99]
  [ 99  99  99]]

 [[ 12  13  14]
  [ 15  16  17]
  [ 18  19  20]
  [ 21  22 100]]]
2483870816560
2483870581552

Process finished with exit code 0

'''

2. ndarray.shape

  • 表示数组的维度,返回一个元组,此元组的长度就是维度的数目,即ndim属性(秩)。二维数组的该元组表示行数和列数。
import numpy as np

a = np.array([[1, 2, 3], [4, 5, 6]])
print(a.shape)
b = np.array([[[1, 2], [3, 4]]])    
print(b)
print(b.shape)

'''运行结果:
(2, 3)
[[[1 2]
  [3 4]]]
(1, 2, 2)
'''
  • 利用shape属性调整数组大小
import numpy as np

# 利用shape属性调整数组大小
a = np.array([[1, 2, 3], [4, 5, 6]])
a.shape = (3, 2)
print(a)

'''运行结果:
[[1 2]
 [3 4]
 [5 6]]
'''

2.1 利用reshape()调整数组大小

  • ndarray.reshape 通常返回的是非拷贝副本,即改变返回后数组的元素,原数组对应元素的值也会改变。
import numpy as np

a = np.array([[1, 2, 3], [4, 5, 6]])
b = a.reshape((3,2))
b[0] = 100   # a、b改变其中一个,两者会相互影响
a[-1] = 99
print(b)
print(a)
print(id(a))   # 1566538454864
print(id(b))   # 1566538455344

'''运行结果:
[[100 100]
 [  3  99]   
 [ 99  99]]
[[100 100   3]
 [ 99  99  99]]
1566538454864
1566538455344
'''

3. ndarray.itemsize

  • itemsize以字节的形式返回数组中每一个元素的大小。
  • 一个元素类型为 float64 的数组 itemsize 属性值为 8(float64 占用 64 个 bits,每个字节长度为 8,所以 64/8,占用 8 个字节)。
  • 一个元素类型为 complex32 的数组 item 属性为 4(32/8)。
import numpy as np

# 数组的dtype为int8(一个字节)
x = np.array([1, 2, 3, 4, 5], dtype=np.int8)
print(x.itemsize)

# 数组的dtype现在为float64(8个字节)
y = np.array([1, 2, 3, 4, 5], dtype=np.float64)
print(y.itemsize)

'''运行结果:
1
8
'''

4. ndarray.flags

  • 该属性返回ndarray对象的内存信息,包含以下属性:
属性 描述
C_CONTIGUOUS (C) 数据是在一个单一的C风格的连续段中。
F_CONTIGUOUS (F) 数据是在一个单一的Fortran风格的连续段中。
OWNDATA (O) 数组拥有它所使用的的内存或从另一个对象中借用它。
WRITEABLE (W) 数据区域可以被写入,将该值设置为False,则数据为只读。
ALIGNED (A) 数据和所有元素都适当地对齐到硬件上。
UPDATEIFCOPY (U) 这个数组是其他数组的一个副本,当这个数组被释放时,原数组的内容将被更新。
import numpy as np

x = np.array([1, 2, 3, 4, 5])
print(x.flags)
'''运行结果:
  C_CONTIGUOUS : True
  F_CONTIGUOUS : True
  OWNDATA : True
  WRITEABLE : True
  ALIGNED : True
  WRITEBACKIFCOPY : False
  UPDATEIFCOPY : False
'''

4. 创建数组

  • ndarray数组除了可以使用底层ndarray构造器来创建外,也可以通过以下几种方式来创建:

1. numpy.empty()

  • numpy.empty()方法用来创建一个指定形状(shape)、数据类型(dtype)且未初始化的数组。

1. numpy.empty()方法的语法

numpy.empty(shape, dtype=float, order= 'C')

2. numpy.empty()参数说明

参数 说明
shape 数组形状
dtype 可选参数,元素的数据类型。
order 有“C”和“F”两个选项,分别代表行优先和列优先,表示在计算机内存中的存储元素顺序。

3. 用empty()方法创建空数组的示例

import numpy as np

x = np.empty([3, 2], dtype=int)
print(x)

'''运行结果
[[         0          0]
 [         0 1071644672]
 [         0 1072693248]]
'''
# 由于数组未初始化,所以数组元素是随机的值

2. numpy.zeros()

  • 创建指定大小的数组,数组元素以0来填充。

1. numpy.zeros()方法的语法

numpy.zeros(shape, dtype=float, order='C')

2. numpy.zeros()参数说明

参数 说明
shape 数组形状。
dtype 数组元素的数据类型,可选参数。
order “C“用于C类型的行数组,或者”F“用于FORTRAN的列数组。

3. 使用numpy.zeros()方法创建数组的示例

import numpy as np

# 默认为浮点数
x = np.zeros(5)
print(x)
# 设置类型为整数
y = np.zeros((5,), dtype=int)
print(y)
# 自定义类型
z = np.zeros((2, 2), dtype=[('x', 'i4'), ('y', 'i4')])
print(z)

'''运行结果:
[0. 0. 0. 0. 0.]
[0 0 0 0 0]
[[(0, 0) (0, 0)]
 [(0, 0) (0, 0)]]
'''

3. numpy.ones()

  • 创建指定形状的数组,数组元素用1来填充。

1. numpy.ones()方法的语法

numpy.ones(shape, dtype=None, order='C')

2. numpy.ones()参数说明

参数 说明
shape 数组形状。
dtype 数据类型,可选参数。
order ’C‘用于C的行数组,’F‘用于FORTRAN的列数组。

3. 用numpy.ones()创建数组的示例

import numpy as np

# 默认为浮点数
x = np.ones(5)
print(x)
# 自定义类型
x = np.ones([2, 2], dtype =int)
print(x)

'''运行结果:
[1. 1. 1. 1. 1.]
[[1 1]
 [1 1]]
'''

5. 从已有的数组创建数组

1. numpy.asarray()

  • numpy.asarray()类似numpy.array(),但其参数只有三个,比numpy.array()少两个。

1. numpy.asarray()方法的语法

numpy.asarray(a, dtype=None, order=None)

2. numpy.asarray()参数说明

参数 说明
a 任意形式的输入参数,可以是列表、列表的元组、元组、元组的元组、元组的列表、多维数组。
dtype 数据类型,可选参数。
order 可选参数,有“C”和“F”两个选项,分别代表行优先和列优先,在计算机内存中的存储元素的顺序。

3. 利用asarray()将各种数据转换为ndarray的示例

  1. 将列表转换为ndarray:
import numpy as np

x = [1, 2, 3]
a = np.asarray(x)
print(a)
print(type(a))

'''运行结果:
[1 2 3]
<class 'numpy.ndarray'>
'''
  1. 将元组转换为ndarray:
import numpy as np

x = (1, 2, 3)
a = np.asarray(x)
print(a)
print(type(a))

'''运行结果:
[1 2 3]
<class 'numpy.ndarray'>
'''
  1. 将元组列表转换为ndarray:
x = [(1, 2, 3), (4, 5, 6)]
a = np.asarray(x)
print(a)
print(type(a))

'''运行结果:
[[1 2 3]
 [4 5 6]]
<class 'numpy.ndarray'>
'''
  1. 设置dtype参数:
import numpy as np

x = [1, 2, 3]
a = np.asarray(x, dtype=float)
print(a)

'''运行结果:
[1. 2. 3.]
'''

2. numpy.frombuffer()

  • numpy.frombuffer()用于实现动态数组
  • numpy.frombuffer()接受buffer输入参数,以流的形式读入转化成ndarray对象。

1. numpy.frombuffer()方法的语法

numpy.frombuffer(buffer, dtype=float, count=-1, offset=0)
  • 注意:buffer是字符串时,Python3默认str是Unicode类型,所以要转成bytestring在原str前加上“b”。

2. numpy.frombuffer()参数说明

参数 描述
buffer 可以是任意对象,会以流的形式读入。
dtype 返回数组的数据类型,可选查参数。
count 读取的数据数量,默认为-1,读取所有数据。
offset 读取的起始位置,默认为0。

3. 利用frombuffer()方法将数据转换为数组的示例

将二进制字符串转换为ndarray:

import numpy as np

s = b'Hello World'
a = np.frombuffer(s, dtype='S1')
print(a)

'''运行结果:
[b'H' b'e' b'l' b'l' b'o' b' ' b'W' b'o' b'r' b'l' b'd']
'''

3. numpy.fromiter()

  • numpy.fromiter()方法从可迭代对象中建立ndarray对象,返回一维数组。

1. numpy.fromiter()方法的语法

numpy.fromiter(iterable, dtype, count=-1)

2. numpy.fromiter()的参数说明

参数 描述
iterable 可迭代对象。
dtype 返回数组的数据类型。
count 读取的数据数量,默认为-1,读取所有数据。

3. 使用fromiter()方法创建数组的示例

import numpy as np

# 使用range函数创建列表对象
list = range(5)
it = iter(list)

# 使用迭代器创建ndarray
x = np.fromiter(it, dtype=float)
print(x)
print(type(x))

'''运行结果:
[0. 1. 2. 3. 4.]
<class 'numpy.ndarray'>
'''

6. 从数值范围创建数组

1. numpy.arange()

  • 使用arange()方法创建数值范围并返回ndarray对象。

1. arange()方法的语法

numpy.arange(start, stop, end, dtype)
  • 根据start与stop指定的范围以及step设定的步长,生成一个ndarray。

2. arange()的参数说明

|参数|说明|
|||
|start|起始值,默认为0。|
|stop|终止值(不包含)。|
|step|步长,默认为1。|
|dtype|返回ndarray的数据类型,如果没有提供,则会使用输入数据的类型。|

3. 使用arange()方法创建数组的示例

  1. 生成0~5的数组:
import numpy as np

x = np.arange(5)
print(x)

'''运行结果:
[0 1 2 3 4]
'''
  1. 利用dtype属性设置返回类型为float:
import numpy as np

# 设置dtype
x = np.arange(5, dtype=float)
print(x)

# 运行结果:[0. 1. 2. 3. 4.]
  1. 设置起始值、终止值及步长:
import numpy as np

x = np.arange(10, 20, 2)
print(x)

# 运行结果:[10 12 14 16 18]

2. numpy.linspace()

  • linspace()方法用于创建一个一维数组,数组是一个等差数列构成的。

1. linspace()方法的语法

np.linspace(start, stop, num=50, endpoint=True, retstep=False, dtype=None)

2. linspace()参数说明

参数 说明
start 序列的起始值。
stop 薛烈的终止值,如果endpoint为True,则该值包含在数列中。
num 要生成的等步长的样本数量,默认为50。
endpoint 该值为True时,数列中包含stop值;反之不包含,默认是True。
retstep 如果为True时,生成的数组中会显示间距,反之不显示。
dtype ndarray的数据类型。

3. 使用linspace()创建数组的示例

  1. 设置起点为1,终点为10,数列个数为10的数组:
import numpy as np

a = np.linspace(1, 1, 10)  
print(a) 

'''运行结果:
[ 1.  2.  3.  4.  5.  6.  7.  8.  9. 10.]
'''                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                          
  1. 设置元素全部都是1的等差数列:
import numpy as np

a = np.linspace(1, 1, 10)
print(a)

'''运行结果:
[1. 1. 1. 1. 1. 1. 1. 1. 1. 1.]
'''
  1. 将endpoint设为False,不包含终止值:
  • 如果将endpoint设为True,则会包含20。
import numpy as np

a = np.linspace(10, 20, 5, endpoint=False)
print(a)

# 运行结果:[10. 12. 14. 16. 18.]
  1. 设置间距
import numpy as np

a = np.linspace(1, 10, 10, retstep=True)
print(a)
# 拓展例子
b = np.linspace(1, 10, 10).reshape([10, 1])
print(b)

'''输出结果:
(array([ 1.,  2.,  3.,  4.,  5.,  6.,  7.,  8.,  9., 10.]), 1.0)
[[ 1.]
 [ 2.]
 [ 3.]
 [ 4.]
 [ 5.]
 [ 6.]
 [ 7.]
 [ 8.]
 [ 9.]
 [10.]]
'''

3. numpy.logspace()

  • numpy.logspace()方法用于创建一个等比数列。

1. logspace()方法的语法

np.logspace(start, stop, num=50, endpoint=True, base=10.0, dtype=None)
  • base参数是对数log的下标。

2. logspace()的参数说明

参数 说明
start 序列的起始值为:base**start
stop 序列的终止值为:base**stop。如果endpoint为true,该值包含于数列中。
num 要生成的等步长的样本数量,默认为50。
endpoint 该值为True时,数列中包含stop值;为False时则不包含。默认是True。
base 对数log的底数。
dtype ndarray的数据类型。

3. 使用logspace()方法创建数组的示例

  1. 使用默认的底数
import numpy as np

# 默认底数是10
a = np.logspace(1.0, 2.0, num=10)
print(a)

'''运行结果:
[ 10.          12.91549665  16.68100537  21.5443469   27.82559402
  35.93813664  46.41588834  59.94842503  77.42636827 100.        ]
'''
  1. 将对数的底数设置为2:
import numpy as np

# 设置底数为2
a = np.logspace(0, 9, 10, base=2)
print(a)

'''运行结果:
[  1.   2.   4.   8.  16.  32.  64. 128. 256. 512.]
'''

7. 切片和索引

  • ndarray对象的内容可以通过索引和切片来访问和修改,与Python中list的切片操作一样。
  • ndarray数组可以基于0~n的下标进行索引,切片对象可以通过内置的slice()方法,并设置start、stop及step参数进行,从原数组中切割出一个新数组。

切片和索引的示例

  1. 通过arange()创建ndarray对象,分别设置起始、终止和步长为2、7、2:
import numpy as np

a = np.arange(10)
s = slice(2, 7, 2)   # 从索引2开始到索引7停止,间隔为2
print(a[s])

# 运行结果:[2 4 6]
  1. 通过冒号分隔切片参数start:stop:step来进行切片操作:
import numpy as np

a = np.arange(10)
b = a[2:7:2]   # 从索引2开始到索引7停止,间隔为2
print(b)

# 运行结果:[2 4 6]
  • 冒号":"的解释:
    • 如果只放置一个参数,如[2],将返回与该索引相对应的单个元素。
    • 如果为[2:],表示从该索引开始以后的所有项都将被提取。
    • 如果使用了两个参数,如[2:7],那么则提取两个索引(不包括停止索引)之间的项。
  1. 一维数组中索引的使用示例
import numpy as np

a = np.arange(10)   # [0 1 2 3 4 5 6 7 8 9]
b = a[5]
print(b)     # 输出结果:5
print(a[2:])   # 输出结果:[2 3 4 5 6 7 8 9]
print(a[2:5])  # 输出结果:[2 3 4]
  1. 多维数组中索引的使用示例:
import numpy as np

a = np.array([[1, 2, 3], [3, 4, 5], [4, 5, 6]])
print(a)
# 从某个索引处开始切割
print("从数组索引 a[1:] 处开始切割")
print(a[1:])

'''运行结果:
[[1 2 3]
 [3 4 5]
 [4 5 6]]
从数组索引 a[1:] 处开始切割
[[3 4 5]
 [4 5 6]]
'''
  1. 包括省略号的切片
  • 切片还可以包括省略号“…”,来使选择元组的长度与数组的维度相同。如果在行位置使用省略号,它将返回包含行中元素的ndarray:
import numpy as np

a = np.array([[1, 2, 3], [3, 4, 5], [4, 5, 6]])
print(a[..., 1])    # 第2列元素
print(a[1, ...])    # 第2行元素
print(a[..., 1:])   # 第2列及剩下的所有元素

'''运行结果:
[2 4 5]
[3 4 5]
[[2 3]
 [4 5]
 [5 6]]
'''

8. 高级索引

  • Numpy比一般的Python序列提供更多的索引方式。
  • 除了之前看到的用整数和切片的索引外,数组可以由整数数组索引、布尔索引及花式索引。

1. 整数数组索引

  1. 获取数组中(0, 0)、(1, 1)和(2, 0)位置处的元素:
import numpy as np

x = np.array([[1, 2], [3, 4], [5, 6]])
y = x[[0, 1, 2], [0, 1, 0]]
print(y)
# 运行结果:[1 4 5]
  1. 获取4*3数组中的四个角的元素,行索引是[0, 0]和[3, 3],而列索引是[0, 2]和[0, 2]:
import numpy as np

x = np.array([[0, 1, 2], [3, 4, 5], [6, 7, 8], [9, 10, 11]])
print("我们的数组是:")
print(x)
print("\n")
rows = np.array([[0, 0], [3, 3]])   # 行索引
cols = np.array([[0, 2], [0, 2]])   # 列索引
y = x[rows, cols]
print('这个数组的四个角元素是:')
print(y)

'''运行结果:
我们的数组是:
[[ 0  1  2]
 [ 3  4  5]
 [ 6  7  8]
 [ 9 10 11]]


这个数组的四个角元素是:
[[ 0  2]
 [ 9 11]]
'''
  • 返回的结果是包含每个角元素的ndarray对象。
  1. 借助切片":“或”…"与索引数组组合的示例:
import numpy as np

a = np.array([[1, 2, 3], [4, 5, 6], [7, 8, 9]])
b = a[1:3, 1:3]
c = a[1:3, [1, 2]]
d = a[..., 1:]
print(b)
print(c)
print(d)

'''运行结果:
[[5 6]
 [8 9]]
[[5 6]
 [8 9]]
[[2 3]
 [5 6]
 [8 9]]
'''

2. 布尔索引

  • 我们可以通过一个布尔数组来索引目标数组。
  • 布尔索引通过布尔运算(如:比较运算符)来获取符合指定条件的元素的数组。
  1. 获取大于5的元素:
import numpy as np

x = np.array([[0, 1, 2], [3, 4, 5], [6, 7, 8], [9, 10, 11]])
print("我们的数组是:")
print(x)
print('\n')
# 现在我们会打印出大于5的元素
print('大于 5 的元素是:')
print(x[x > 5])
'''运行结果:
我们的数组是:
[[ 0  1  2]
 [ 3  4  5]
 [ 6  7  8]
 [ 9 10 11]]


大于 5 的元素是:
[ 6  7  8  9 10 11]
'''
  1. 使用~(取补运算符)来过滤NaN:
import numpy as np

a = np.array([np.nan, 1, 2, np.nan, 3, 4, 5])
print(a[~np.isnan(a)])

# 运行结果:[1. 2. 3. 4. 5.]
  1. 从数组中过滤掉非复数元素:
import numpy as np

a = np.array([1, 2+6j, 5, 3.5+5j])
print(a[np.iscomplex(a)])

# 运行结果:[2. +6.j 3.5+5.j]

3. 花式索引

  • 花式索引指的是利用整数数组进行索引。
  • 花式索引根据索引数组的值作为目标数组的某个轴的下标来取值。
  • 对于使用一维整型数组作为索引,如果目标是一维数组,那么索引的结果就是对应位置的元素,如果目标是二维数组,那么就是对应下标的行。
  • 花式索引跟切片不一样,它总是将数据复制到新数组中。

1. 一维数组

  • 一维数组只有一个轴axis=0,所以一维数组就在axis=0这个轴上取值:
import numpy as np

x = np.arange(9)
print(x)
# 一维数组读取指定下标对应的元素
print("------读取下标对应的元素------")
x2 = x[[0, 6]]    # 使用花式索引
print(x2)

print(x2[0])
print(x2[1])

'''运行结果:
[0 1 2 3 4 5 6 7 8]
------读取下标对应的元素------
[0 6]
0
6
'''

2. 二维数组

  1. 传入顺序索引数组:
import numpy as np

x = np.arange(32).reshape((8, 4))
print(x)
# 二维数组读取指定下标对应的行
print("------读取下标对应的行------")
print(x[[4, 2, 1, 7]])
# print (x[[4,2,1,7]]) 输出下表为 4, 2, 1, 7 对应的行

'''运行结果:
[[ 0  1  2  3]
 [ 4  5  6  7]
 [ 8  9 10 11]
 [12 13 14 15]
 [16 17 18 19]
 [20 21 22 23]
 [24 25 26 27]
 [28 29 30 31]]
------读取下标对应的行------
[[16 17 18 19]
 [ 8  9 10 11]
 [ 4  5  6  7]
 [28 29 30 31]]
'''
  1. 传入倒序索引数组:
import numpy as np

x = np.arange(32).reshape((8, 4))
print(x[[-4, -2, -1, -7]])

'''运行结果:
[[16 17 18 19]
 [24 25 26 27]
 [28 29 30 31]
 [ 4  5  6  7]]
'''
  1. 传入多个索引数组(要使用np.ix_)
  • np.ix_函数就是输入两个数组,产生笛卡尔积的映射关系
  • 笛卡尔积是指在数学中,两个集合X和Y的笛卡尔积(Cartesian product),又称直积,表示X x Y,第一个对象是X的成员而第二个对象是Y的所有可能有序对的其中一个成员。
  • 例如A={a,b},B={0,1, 2},则:
A x B = {
    
    (a, 0), (a, 1), (a, 2), (b, 0), (b, 1), (b, 2)}
B x A = {
    
    (0, a), (a, b), (1, a), (a, b), (2, a), (2, b)}
import numpy as np

x =np.arange(32).reshape((8, 4))    # 8行4列
print(x[np.ix_([1, 5, 7, 2], [0, 3, 1, 2])]) 

输出结果为:

[[ 4  7  5  6]
 [20 23 21 22]
 [28 31 29 30]
 [ 8 11  9 10]]  

整个流程如下:
在这里插入图片描述

9. 广播(Broadcast)

  • 广播(Broadcast)是numpy对不同形状(shape)的数组进行数值计算的方式,对数组的算术运算通常在相应的元素上进行。
  • 如果两个数组a和b的形状相同,即满足a.shape == b.shape,那么a*b的结果就是a与b数组对应位相乘。这要求维数相同,且各维度的长度相同。

1. 正常广播的示例

  1. 形状相同的数组相乘:
import numpy as np

a = np.array([1, 2, 3, 4])
b = np.array([10, 20, 30, 40])
c = a * b
print(c)

输出结果为:

[10 40 90 160]
  1. 有一个维度相同的数组相加:
  • 当运算中的2个数组的形状不同时,numpy将自动触发广播机制。
import numpy as np

a = np.array([[0, 0, 0], [10, 10, 10], [20, 20, 20], [30, 30, 30]])
b = np.array([0, 1, 2])
print(a + b)

输出结果为:

[[ 0  1  2]
 [10 11 12]
 [20 21 22]
 [30 31 32]]

下图展示了数组b如何通过广播来与数组b兼容:
在这里插入图片描述
4x3的二维数组与长为3的一维数组相加,等效于把数组b在二维上重复4次再运算:

import numpy as np

a = np.array([[0, 0, 0], [10, 10, 10], [20, 20, 20], [30, 30, 30]])
b = np.array([0, 1, 2])
bb = np.tile(b, (4, 1))     # 重复b的各个维度
print(a + bb)

运行结果和将两个不同维度的数组相加的结果一样:

[[ 0  1  2]
 [10 11 12]
 [20 21 22]
 [30 31 32]]
  1. 有一个维度为1的数组相加:
import numpy as np

a = np.array([1])
b = np.array([[10, 10],[20, 20]])
print(a+b)

运行结果:

[[11 11]
 [21 21]]

2. 会出现报错的示例:

  1. 两个数组的不同维度都超出对方的情况:
import numpy as np

a = np.array([1, 2, 3, 4])
b = np.array([[10, 10, 10], [20, 20, 20]])
print(a+b)

这种情况会出现报错:
在这里插入图片描述

  1. 维度与对方均不符合
import numpy as np

a = np.array([1, 2])
b = np.array([[10, 10, 10], [20, 20, 20]])
print(a+b)

运行结果:
在这里插入图片描述

  1. 维度与对方不符合
import numpy as np

a = np.array([[1, 2], [1, 2]])
b = np.array([[10, 10, 10], [20, 20, 20]])
print(a+b)

运行结果:
在这里插入图片描述

2. 广播的规则

  • 让所有数组都向其中形状最长的数组看齐,形状中不足的部分都通过在前面加1补齐。
  • 输出数组的形状是输入数组形状的各个维度上的最大值。
  • 如果输入数组的某个维度和输出数组的对应维度的长度相同或者其长度为1时,这个数组能够用来计算,否则出错。
  • 当输入数组的某个维度的长度为1时,沿着此维度运算时都用此维度上的第一组值。

对以上规则的理解

  • 对两个数组,分别比较他们的每一个维度(若其中一个数组没有当前维度则忽略),满足:
    • 数组拥有相同形状。
    • 当前维度的值相等。
    • 当前维度的值有一个是1。
  • 若条件不满足,抛出“ValueError: frames are not aligned”异常。

10. 迭代数组

  • Numpy迭代器对象numpy nditer提供了一种灵活访问一个或者多个数组元素的方式。
  • 迭代器最基本的任务的可以完成对数组元素的访问。

1. 使用nditer迭代数组的示例

  1. 使用arange()函数创建一个2x3数组,并使用nditer对它进行迭代:
import numpy as np

a = np.arange(6).reshape(2, 3)
print('原始数组是:')
print(a)
print('\n')
print('迭代输出元素:')
for x in np.nditer(a):
	print(x, end=", ")
print('\n')

输出结果是:

原始数组是:
[[0 1 2]
 [3 4 5]]


迭代输出元素:
0, 1, 2, 3, 4, 5,
  • 以上示例不是使用标准C或者Fortran顺序,选择的顺序是和数组内存布局一致的,这样做是为了提升访问效率,默认是行序优先(row-major order,或者说是C-order)。
  • 这反映了默认情况下只需访问每个元素,而无需考虑其特定顺序。我们可以通过迭代上述数组的转置来看到这一点,并以C顺序访问数组转置的copy方式做对比。
  1. 迭代数组的转置和以C顺序访问数组转置的副本的对比:
import numpy as np

a = np.arange(6).reshape(2, 3)
for x in np.nditer(a.T):
	print(x, end=", ")
print('\n')
for x in np.nditer(a.T.copy(order='C')):
	print(x, end=", ")
print('\n')

运行结果:

0, 1, 2, 3, 4, 5, 

0, 3, 1, 4, 2, 5, 
  • a和a.T的遍历顺序是一样的,也就是他们在内存中的存储顺序也是一样的,但是a.T.copy(order=‘C’)的遍历结果是不同的,那是因为它和前两种的存储方式是不一样的,默认是按行访问

2. 控制遍历顺序

  • for x in np.nditer(a, order=‘F’):Fortran order,即是列序优先;
  • for x in np.nditer(a.T, order=‘C’):C order,即是行序优先。
import numpy as np

a = np.arange(0, 60, 5)
a = a.reshape(3, 4)
print('原始数组是:')
print(a)
print('\n')
print('原始数组的转置是:')
b = a.T
print(b)
print('\n')
print('以C风格顺序排序:')
c = b.copy(order='C')
print(c)
for x in np.nditer(c):
	print(x, end=", ")
print('\n')
print('以F风格顺序排序:')
c = b.copy(order='F')
print(c)
for x in np.nditer(c):
	print(x, end=", ")

输出结果是:

原始数组是:
[[ 0  5 10 15]
 [20 25 30 35]
 [40 45 50 55]]


原始数组的转置是:
[[ 0 20 40]
 [ 5 25 45]
 [10 30 50]
 [15 35 55]]


以C风格顺序排序:
[[ 0 20 40]
 [ 5 25 45]
 [10 30 50]
 [15 35 55]]
0, 20, 40, 5, 25, 45, 10, 30, 50, 15, 35, 55, 

以F风格顺序排序:
[[ 0 20 40]
 [ 5 25 45]
 [10 30 50]
 [15 35 55]]
0, 5, 10, 15, 20, 25, 30, 35, 40, 45, 50, 55, 

可以通过显示设置,来强制nditer对象使用某种顺序:

import numpy as np

a = np.arange(0, 60, 5)
a = a.reshape(3, 4)
print('原始数组是:')
print(a)
print('\n')
print('以C风格顺序排序:')
for x in np.nditer(a, order='C'):
	print(x, end=", ")
print("\n)
print('以F风格顺序排序:')
for x in np.nditer(a, order='F'):
	print(x, end=", ")

输出结果为:

原始数组是:
[[ 0  5 10 15]
 [20 25 30 35]
 [40 45 50 55]]


以C风格顺序排序:
0, 5, 10, 15, 20, 25, 30, 35, 40, 45, 50, 55, 

以F风格顺序排序:
0, 20, 40, 5, 25, 45, 10, 30, 50, 15, 35, 55, 

3. 修改数组中元素的值

  • nditer对象有另一个可选参数op_flags。默认情况下,nditer将视待迭代遍历的数组为只读对象(read-only),为了在遍历数组的同时,实现对数组元素值得修改,必须指定readwrite或者writeonly的模式。
import numpy as np

a = np.arange(0, 60, 5)
a = a.reshape(3, 4)
print('原始数组是:')
print(a)
print('\n')
for x in np.nditer(a, op_flags=['readwrite']):
	x[...] = 2 * x
print('修改后的数组是:')
print(a)

运行结果如下:

原始数组是:
[[ 0  5 10 15]
 [20 25 30 35]
 [40 45 50 55]]


修改后的数组是:
[[  0  10  20  30]
 [ 40  50  60  70]
 [ 80  90 100 110]]

4. 使用外部循环

  • nditer类的构造器拥有flags参数,它可以接受下列值:
参数 说明
c_index 可以跟踪C顺序的索引。
f_index 可以跟踪Fortran顺序的索引。
multi_index 每次迭代可以跟踪一种索引类型。
external_loop 给出的值是具有多个值的一维数组,而不是零维数组。

下面实例中,迭代器遍历对应于每列,并组合为一维数组:

import numpy as np

a = np.arange(0, 60, 5)
a = a.reshape(3, 4)
print('原始数组是:')
print(a)
print('\n')
print('修改后的数组是:')
for x in np.nditer(a, flags=['external_loop'], order='F'):
	print(x, end=", ")

输出结果为:

原始数组是:
[[ 0  5 10 15]
 [20 25 30 35]
 [40 45 50 55]]


修改后的数组是:
[ 0 20 40], [ 5 25 45], [10 30 50], [15 35 55], 

5. 广播迭代

  • 如果两个数组是可广播的,nditer组合对象能够同时迭代它们。假设数组a的维度为3X4,数组b的维度为1x4,则使用以下迭代器(数组b被广播到a的大小)。
import numpy as np

a = np.arange(0, 60, 5)
a = a.reshape(3, 4)
print('第一个数组为:')
print(a)
print('\n')
print('第二个数组为:')
b = np.array([1, 2, 3, 4], dtype=int)
print(b)
print('\n')
print('修改后的数组为:')
for x, y in np.nditer([a, b]):
	print("%d:%d" % (x, y), end=", ")

运行结果为:

第一个数组为:
[[ 0  5 10 15]
 [20 25 30 35]
 [40 45 50 55]]


第二个数组为:
[1 2 3 4]


修改后的数组为:
0:1, 5:2, 10:3, 15:4, 20:1, 25:2, 30:3, 35:4, 40:1, 45:2, 50:3, 55:4, 

11. 数组操作

  • Numpy中包含了一些函数用于处理数组,大概可分为六类:修改数组形状、翻转数组、修改数组维度、连接数组、分割数组、数组元素的添加与删除。

1. 修改数组形状

函数 描述
reshape 不改变数据的条件下修改形状。
flat 数组元素迭代器。
flatten 返回一份数组拷贝,对拷贝所做的修改不会影响原始数组。
ravel 返回展开数组。

1. numpy.reshape()

  • 该方法可以在不改变数据的条件下修改形状,方法说明如下:
numpy.reshape(arr, newshape, order='C')
# arr:要修改形状的数组。
# newshape:整数或者整数数组,新的形状应当兼容原有形状。
# order:‘C’——按行;‘F’——按列;‘A’——原顺序;‘K’——元素在内存中的出现顺序。
import numpy as np

a = np.arange(8)
print('原始数组:')
print(a)
print('\n')

b = a.reshape(4, 2)   # 4行2列
print('修改后的数组:')
print(b)

运行结果如下:

原始数组:
[0 1 2 3 4 5 6 7]


修改后的数组:
[[0 1]
 [2 3]
 [4 5]
 [6 7]]

reshape()中只设置一个参数:

size = np.array([[1, 2], [3, 4]])
size1 = size.reshape(4)
print("size = ", size, '\nsize1 = ', size1)

运行结果:

size =  [[1 2]
 [3 4]] 
size1 =  [1 2 3 4]

2. numpy.ndarray.flat()

  • numpy.ndarray.flat是一个数组元素迭代器。
import numpy as np

a = np.arange(9).reshape(3, 3)
print('原始数组:')
for row in a:
	print(row)

# 对数组中每个元素都进行处理,可以使用flat属性,该属性是一个数组元素迭代器:
print('迭代后的数组:')
for element in a.flat:
	print(element)

输出的结果如下:

原始数组:
[0 1 2]
[3 4 5]
[6 7 8]
迭代后的数组:
0
1
2
3
4
5
6
7
8

3. numpy.ndarray.flatten()

  • numpy.ndarray.flatten返回一份数组拷贝,对拷贝所做的修改不会影响原始数组,格式如下:
ndarray.flatten(order='C')
# order:‘C’——按行;‘F’——按列;‘A’——原顺序;‘K’——元素在内存中的出现顺序。
import numpy as np

a = np.arange(8).reshape(2, 4)
print('原数组:')
print(a)
print('\n')
# 默认按行

print('展开的数组:')
print(a.flatten())
print('\n')

print('以F风格顺序展开的数组:')
print(a.flatten(order='F'))

运行结果:

原数组:
[[0 1 2 3]
 [4 5 6 7]]


展开的数组:
[0 1 2 3 4 5 6 7]


以F风格顺序展开的数组:
[0 4 1 5 2 6 3 7]

4. numpy.ravel()

  • numpy.ravel()展平的数组元素,顺序通常是“C风格”,返回的是数组视图(view,有点类似C/C++引用reference的意味),修改会影响原始数组。
  • 该函数接收两个参数:
numpy.ravel(a, order='C')
# order:‘C’——按行;‘F’——按列;‘A’——原顺序;‘K’——元素在内存中的出现顺序。
import numpy as np

a = np.arange(8).reshape(2, 4)
print('原数组:')
print(a)
print('\n')

print('调用ravel函数之后:')
print(a.ravel())
print('\n')

print('以F风格顺序调用ravel函数之后:')
print(a.ravel(order='F'))

运行结果如下:

原数组:
[[0 1 2 3]
 [4 5 6 7]]


调用ravel函数之后:
[0 1 2 3 4 5 6 7]


以F风格顺序调用ravel函数之后:
[0 4 1 5 2 6 3 7]

2. 翻转数组

函数 说明
transpose 对换数组的维度。
ndarray.T 和self.transpose()相同。
rollaxis 向后滚动指定的轴。
swapaxes 对换数组的两个轴。

1. numpy.transpose()

  • numpy.transpose()函数用于对换数组的维度,格式如下:
numpy.transpose(arr, axes)
# arr:要操作的数组。
# axes:整数列表,对应维度,通常所有维度都会对换。
import numpy as np

a = np.arange(12).reshape(3, 4)
print('原数组:')
print(a)
print('\n')

print('对换数组:')
print(np.transpose(a))

运行结果如下:

原数组:
[[ 0  1  2  3]
 [ 4  5  6  7]
 [ 8  9 10 11]]


对换数组:
[[ 0  4  8]
 [ 1  5  9]
 [ 2  6 10]
 [ 3  7 11]]
  • 指定axes参数,实现数组翻转:
a = np.arange(0, 12).reshape(2, 2, 3)
print(a)
print(np.where(a == 6))
a_t = np.transpose(a, axes=(1, 2, 0))
print(a_t)
print(a_t.shape)
print(np.where(a_t == 6))

运行结果:

[[[ 0  1  2]
  [ 3  4  5]]

 [[ 6  7  8]
  [ 9 10 11]]]
(array([1], dtype=int64), array([0], dtype=int64), array([0], dtype=int64))
[[[ 0  6]
  [ 1  7]
  [ 2  8]]

 [[ 3  9]
  [ 4 10]
  [ 5 11]]]
(2, 3, 2)
(array([0], dtype=int64), array([0], dtype=int64), array([1], dtype=int64))

2. numpy.ndarray.T

  • 类似numpy.transpose:
import numpy as np

a = np.arange(12).reshape(3, 4)
print('原数组:')
print(a)
print('\n')

print('转置数组:')
print(a.T)

运行结果如下:

原数组:
[[ 0  1  2  3]
 [ 4  5  6  7]
 [ 8  9 10 11]]


转置数组:
[[ 0  4  8]
 [ 1  5  9]
 [ 2  6 10]
 [ 3  7 11]]

3. numpy.rollaxis()

  • numpy.rollaxis()函数向后滚动特定的轴到一个特定位置,格式如下:
numpy.rollaxis(arr, axis, start)
# arr:数组。
# axis:要向后滚动的轴,其他轴的相对位置不会改变。
# start:默认为0,表示完整的滚动。会滚动到特定位置。
import numpy as np

# 创建了三维的ndarray
a = np.arange(8).reshape(2, 2, 2)
print('原数组:')
print(a)
print('获取数组中的一个值:')
print(np.where(a==6))
print(a[1, 1, 0])   # 为6
print('\n')

# 将轴2滚动到轴0(宽度到深度)
print('调用rollaxis函数:')
b = np.rollaxis(a, 2, 0)
print(b)
# 查看元素a[1, 1, 0], 即6的坐标,变成[0, 1, 1]
# 最后一个0移动到最前面
print(np.where(b==6))
print('\n')

# 将轴2滚动到轴1:(宽度到高度)

print('调用rollaxis函数:')
c = np.rollaxis(a, 2, 1)
print(c)
# 查看元素a[1, 1, 0],即6的坐标,变成[1, 0, 1]
# 最后的0和它前面的1对换位置
print(np.where(c==6))
print('\n')

运行结果如下:

原数组:
[[[0 1]
  [2 3]]

 [[4 5]
  [6 7]]]
获取数组中的一个值:
(array([1], dtype=int64), array([1], dtype=int64), array([0], dtype=int64))
6


调用rollaxis函数:
[[[0 2]
  [4 6]]

 [[1 3]
  [5 7]]]
(array([0], dtype=int64), array([1], dtype=int64), array([1], dtype=int64))


调用rollaxis函数:
[[[0 2]
  [1 3]]

 [[4 6]
  [5 7]]]
(array([1], dtype=int64), array([0], dtype=int64), array([1], dtype=int64))

4. numpy.swapaxes()

  • numpy.swapaxes()函数用于交换数组的两个轴,格式如下:
numpy.swapaxes(arr, axis1, axis2)
# arr:输入的数组。
# axis1:对应第一个轴的整数。
# axis2:对应第二个轴的整数。
import numpy as np

# 创建了三维的ndarray
a = np.arange(8).reshape(2, 2, 2)

print('原数组:')
print(a)
print('\n')
# 现在交换轴0(深度方向)到轴2(宽度方向)

print('调用swapaxes函数后的数组:')
print(np.swapaxes(a, 2, 0))

输出结果如下:

原数组:
[[[0 1]
  [2 3]]

 [[4 5]
  [6 7]]]


调用swapaxes函数后的数组:
[[[0 4]
  [2 6]]

 [[1 5]
  [3 7]]]

3. 修改数组维度

维度 描述
broadcast 产生模仿广播的对象。
broadcast_to 将数组广播到新形状。
expand_dims 扩展数组的形状。
squeeze 从数组的形状中删除一维条目。

1. numpy.broadcast()

  • numpy.broadcast用于模仿广播的对象,它返回一个对象,该对象封装了将一个数组广播到另一个数组的结果。
    该函数使用两个数组作为输入参数,实例如下:
import numpy as np

x = np.array([[1], [2], [3]])
y = np.array([4, 5, 6])

# 对y广播x
b = np.broadcast(x, y)
# 它拥有iterator属性,基于自身组件的迭代器元组。

print('对y广播x:')
r, c = b.iters

# Python3.x为next(context),Python2.x为context.next()
print(next(r), next(c))
print(next(r), next(c))
print('\n')
# shape 属性返回广播对象的形状

print('广播对象的形状:')
print(b.shape)
print('\n')
# 手动使用broadcast将x与y相加
b = np.broadcast(x, y)
c = np.empty(b.shape)

print('手动使用broadcast将x与y相加:')
print(b.shape)
print('\n')
c.flat = [u + v for (u, v) in b]

print('调用flat函数:')
print(c)
print('\n')
# 获得了和Numpy内建的广播支持相同的结果

print('x与y的和:')
print(x + y)

运行结果如下:

对y广播x:
1 4
1 5


广播对象的形状:
(3, 3)


手动使用broadcast将x与y相加:
(3, 3)


调用flat函数:
[[5. 6. 7.]
 [6. 7. 8.]
 [7. 8. 9.]]


x与y的和:
[[5 6 7]
 [6 7 8]
 [7 8 9]]

2. numpy.broadcast_to()

  • numpy.broadcast_to函数将数组广播到新形状。它在原始数组上返回只读视图。它通常不连续。如果新形状不符合Numpy的广播规则,该函数可能会抛出ValueError。
numpy.broadcast_to(array, shape, subok)
import numpy as np

a = np.arange(4).reshape(1, 4)

print('原数组:')
print(a)
print('\n')

print('调用broadcast_to函数之后:')
print(np.broadcast_to(a, (4, 4)))

运行结果为:

[[0 1 2 3]]


调用broadcast_to函数之后:
[[0 1 2 3]
 [0 1 2 3]
 [0 1 2 3]
 [0 1 2 3]]

3. numpy.expand_dims()

  • numpy.expand_dims()函数通过在指定位置插入新的轴来扩展数组形状,函数格式如下:
numpy.expand_dims(arr, axis)
# arr:输入数组。
# axis:新轴插入的位置。
import numpy as np

x = np.array(([1, 2], [3, 4]))

print('数组 x:')
print(x)
print('\n')
y = np.expand_dims(x, axis=0)

print('数组 y:')
print(y)
print('\n')

print('数组x和数组y的形状:')
print(x.shape, y.shape)
print('\n')
# 在位置1插入轴
y = np.expand_dims(x, axis=1)

print('在位置1插入轴之后的数组y:')
print(y)
print('\n')

print('x.ndim 和 y.ndim:')
print(x.ndim, y.ndim)
print('\n')

print('x.shape和y.shape:')
print(x.shape, y.shape)

输出结果为:

数组 x:
[[1 2]
 [3 4]]


数组 y:
[[[1 2]
  [3 4]]]


数组x和数组y的形状:
(2, 2) (1, 2, 2)


在位置1插入轴之后的数组y:
[[[1 2]]

 [[3 4]]]


x.ndim 和 y.ndim:
2 3


x.shape和y.shape:
(2, 2) (2, 1, 2)

4. numpy.squeeze()

  • numpy.squeeze()函数从给定数组的形状中删除一维的条目,函数格式如下:
numpy.squeeze(arr, axis)
# arr:输入数组。
# axis:整数或整数元组,用于选择形状中一维条目的子集。
import numpy as np

x = np.arange(9).reshape(1, 3, 3)
print('数组x:')
print(x)
print('\n')
y = np.squeeze(x)

print('数组 y:')
print(y)
print('\n')

print('数组x和y的形状:')
print(x.shape, y.shape)

输出的结果为:

数组x:
[[[0 1 2]
  [3 4 5]
  [6 7 8]]]


数组 y:
[[0 1 2]
 [3 4 5]
 [6 7 8]]


数组x和y的形状:
(1, 3, 3) (3, 3)

4. 连接数组

函数 描述
concatenate 连接沿线有轴的数组序列。
stack 沿着新的轴加入一系列数组。
hstack 水平堆叠序列中的数组(列方向)。
vstack 竖直堆叠序列中的数组(行方向)。

1. numpy.concatenate()

  • numpy.concatenate()函数用于沿指定轴连接相同形状的两个或多个数组,格式如下:
numpy.concatenate((a1, a2, ...), axis)
# a1, a2, ...:相同类型的数组。
# axis:沿着它连接数组的轴,默认为0。
import numpy as np

a = np.array([[1, 2], [3, 4]])

print('第一个数组:')
print(a)
print('\n')
b = np.array([[5, 6], [7, 8]])

print('第二个数组:')
print(b)
print('\n')
# 两个数组的维度相同

print('沿轴0连接两个数组:')
print(np.concatenate((a, b)))
print('\n')

print('沿轴1连接两个数组:')
print(np.concatenate((a, b), axis=1))

运行结果:

第一个数组:
[[1 2]
 [3 4]]


第二个数组:
[[5 6]
 [7 8]]


沿轴0连接两个数组:
[[1 2]
 [3 4]
 [5 6]
 [7 8]]


沿轴1连接两个数组:
[[1 2 5 6]
 [3 4 7 8]]

2. numpy.stack()

  • numpy.stack函数用于沿新轴连接数组序列,格式如下:
numpy.stack(arrays, axis)
# arrays:相同形状的数组序列。
# axis:返回数组中的轴,输入数组沿着它来堆叠。
import numpy as np

a = np.array([[1, 2], [3, 4]])
print('第一个数组:')
print(a)
print('\n')
b = np.array([[5, 6], [7, 8]])

print('第二个数组:')
print(b)
print('\n')

print('沿轴0堆叠两个数组:')
print(np.stack((a, b), 0))
print('\n')

print('沿轴1堆叠两个数组:')
print(np.stack((a, b), 1))

运行结果:

第一个数组:
[[1 2]
 [3 4]]


第二个数组:
[[5 6]
 [7 8]]


沿轴0堆叠两个数组:
[[[1 2]
  [3 4]]

 [[5 6]
  [7 8]]]


沿轴1堆叠两个数组:
[[[1 2]
  [5 6]]

 [[3 4]
  [7 8]]]

3. numpy.hstack()

  • numpy.hstack()是numpy.stack()函数的变体,它通过水平堆叠来生成数组。
import numpy as np

a = np.array([[1, 2], [3, 4]])

print('第一个数组:')
print(a)
print('\n')
b = np.array([[5, 6], [7, 8]])

print('第二个数组:')
print(b)
print('\n')

print('水平堆叠:')
c = np.hstack((a, b))
print(c)
print('\n')

输出结果如下:

第一个数组:
[[1 2]
 [3 4]]


第二个数组:
[[5 6]
 [7 8]]


水平堆叠:
[[1 2 5 6]
 [3 4 7 8]]

4. numpy.vstack()

  • numpy.vstack()是numpy.stack()函数的变体,它通过垂直堆叠来生成数组。
import numpy as np

a = np.array([[1, 2], [3, 4]])

print('第一个数组:')
print(a)
print('\n')
b = np.array([[5, 6], [7, 8]])

print('第二个数组:')
print(b)
print('\n')

print('竖直堆叠:')
c = np.vstack((a, b))
print(c)

输出结果为:

第一个数组:
[[1 2]
 [3 4]]


第二个数组:
[[5 6]
 [7 8]]


竖直堆叠:
[[1 2]
 [3 4]
 [5 6]
 [7 8]]

5. 分割数组

函数 数组及操作
split 将一个数组分割为多个子数组。
hsplit 将一个数组水平分割为多个子数组(按列)。
vsplit 将一个数组垂直分割为多个子数组(按行)。

1. numpy.split()

  • numpy.split()函数沿特定的轴将数组分割为子数组,格式如下:
numpy.split(ary, indices_or_sections, axis)
# ary:被分割的数组。
# indices_or_sections:如果是一个整数,就用该数平均切分,如果是一个数组,为沿轴切分的位置(左开右闭)。
# axis:设置沿着哪个方向进行切分,默认为0,横向切分,即水平方向。为1时,纵向切分,即竖直方向。
import numpy as np

																																																														a = np.arange(9)
print('第一个数组:')
print(a)
print('\n')

print('将数组分为三个大小相等的子数组:')
b = np.split(a, 3)
print(b)
print('\n')

print('将数组在一维数组中表明的位置分割:')
b = np.split(a, [4, 7])
print(b)																

输出结果为:

第一个数组:
[0 1 2 3 4 5 6 7 8]


将数组分为三个大小相等的子数组:
[array([0, 1, 2]), array([3, 4, 5]), array([6, 7, 8])]


将数组在一维数组中表明的位置分割:
[array([0, 1, 2, 3]), array([4, 5, 6]), array([7, 8])]

axis为0时在水平方向分割,axis为1时在垂直方向分割:

import numpy as np

a = np.arange(16).reshape(4, 4)
print('第一个数组:')
print(a)
print('\n')
print('默认分割(0轴):')
b = np.split(a, 2)
print(b)
print('\n')

print('沿水平方向分割:')
c = np.split(a, 2, 1)
print(c)
print('\n')

print('沿水平方向分割:')
d = np.hsplit(a, 2)
print(d)

输出结果为:

第一个数组:
[[ 0  1  2  3]
 [ 4  5  6  7]
 [ 8  9 10 11]
 [12 13 14 15]]


默认分割(0轴):
[array([[0, 1, 2, 3],
       [4, 5, 6, 7]]), array([[ 8,  9, 10, 11],
       [12, 13, 14, 15]])]


沿水平方向分割:
[array([[ 0,  1],
       [ 4,  5],
       [ 8,  9],
       [12, 13]]), array([[ 2,  3],
       [ 6,  7],
       [10, 11],
       [14, 15]])]


沿水平方向分割:
[array([[ 0,  1],
       [ 4,  5],
       [ 8,  9],
       [12, 13]]), array([[ 2,  3],
       [ 6,  7],
       [10, 11],
       [14, 15]])]

2. numpy.hsplit()

  • numpy.hsplit()函数用于水平分割数组,通过指定要返回的相同形状的数组数量来拆分原数组。
import numpy as np

harr = np.floor(10 * np.random.random((2, 6)))
print('原array:')
print(harr)

print('拆分后:')
print(np.hsplit(harr, 3))

运行结果:

原array:
[[1. 7. 8. 6. 1. 0.]
 [4. 8. 9. 9. 2. 9.]]
拆分后:
[array([[1., 7.],
       [4., 8.]]), array([[8., 6.],
       [9., 9.]]), array([[1., 0.],
       [2., 9.]])]

3. numpy.vsplit()

  • numpy.vsplit()沿着垂直轴分割,其分割方式与hsplit用法相同。
import numpy as np

a = np.arange(16).reshape(4, 4)
print('第一个数组:')
print(a)
print('\n')

print('竖直分割:')
b = np.vsplit(a, 2)
print(b)

运行结果:

第一个数组:
[[ 0  1  2  3]
 [ 4  5  6  7]
 [ 8  9 10 11]
 [12 13 14 15]]


竖直分割:
[array([[0, 1, 2, 3],
       [4, 5, 6, 7]]), array([[ 8,  9, 10, 11],
       [12, 13, 14, 15]])]

6. 数组元素的添加与删除

函数 元素及描述
resize 返回指定形状的新数组。
append 将值添加到数组末尾。
insert 沿指定轴将值插入到指定下标之前。
delete 删掉某个轴的子数组,并返回删除后的新数组。
unique 查找数组内的唯一元素。

1. numpy.resize()

  • numpy.resize()函数返回指定大小的新数组。
  • 如果新数组大小大于原始大小,则包含原始数组中的元素的副本。
numpy.resize(arr, shape)
# arr:要修改大小的数组。
# shape:返回数组的新形状。
import numpy as np

a = np.array([[1, 2, 3], [4, 5, 6]])

print('第一个数组:')
print(a)
print('\n')

print('第一个数组的形状:')
print(a.shape)
print('\n')
b = np.resize(a, (3, 2))

print('第二个数组:')
print(b)
print('\n')

print('第二个数组的形状:')
print(b.shape)
print('\n')
# 要注意a的第一行在b中重复出现,因为尺寸变大了。

print('修改第二个数组的大小:')
b = np.resize(a, (3, 3))
print(b)

输出结果为:

第一个数组:
[[1 2 3]
 [4 5 6]]


第一个数组的形状:
(2, 3)


第二个数组:
[[1 2]
 [3 4]
 [5 6]]


第二个数组的形状:
(3, 2)


修改第二个数组的大小:
[[1 2 3]
 [4 5 6]
 [1 2 3]]

2. numpy.append()

  • numpy.append()函数在数组的末尾添加值。追加操作会分配整个数组,并把原来的数组复制到新数组中。此外,输入数组的维度必须匹配否则生成ValueError。
  • append()函数返回的始终是一个一维数组。
import numpy as np

a = np.array([[1, 2, 3], [4, 5, 6]])

print('第一个数组:')
print(a)
print('\n')

print('向数组添加元素:')
print(np.append(a, [7, 8, 9]))
print('\n')

print('沿轴0添加元素:')
print(np.append(a, [[7, 8, 9]], axis=0))
print('\n')

print('沿轴1添加元素:')
print(np.append(a, [[5, 5, 5], [7, 8, 9]], axis=1))

运行结果如下:

第一个数组:
[[1 2 3]
 [4 5 6]]


向数组添加元素:
[1 2 3 4 5 6 7 8 9]


沿轴0添加元素:
[[1 2 3]
 [4 5 6]
 [7 8 9]]


沿轴1添加元素:
[[1 2 3 5 5 5]
 [4 5 6 7 8 9]]

3. numpy.insert()

  • numpy.insert()函数在给定索引之前,沿给定轴在输入数组中插入值。
  • 如果值的类型转换为要插入,则它与输入数组不同。插入没有原地的,函数会返回一个新数组。此外,如果未提供轴,则输入数组会被展开。
numpy.insert(arr, obj, values, axis)
# arr:输入数组。
# obj:在其之前插入值的索引。
# values:要插入的值。
# axis:沿着它插入的轴,如果未提供,则输入数组会被展开。
import numpy as np

a = np.array([[1, 2], [3, 4], [5, 6]])

print('第一个数组:')
print(a)
print('\n')

print('未传递Axis参数。在删除之前输入数组会被展开。')
print(np.insert(a, 3, [11, 12]))
print('\n')
print('传递了Axis参数。会广播值数组来配输入数组。')

print('沿轴0广播:')
print(np.insert(a, 1, [11], axis=0))
print('\n')

print('沿轴1广播:')
print(np.insert(a, 1, 11, axis=1))

输出结果如下:

第一个数组:
[[1 2]
 [3 4]
 [5 6]]


未传递Axis参数。在删除之前输入数组会被展开。
[ 1  2  3 11 12  4  5  6]


传递了Axis参数。会广播值数组来配输入数组。
沿轴0广播:
[[ 1  2]
 [11 11]
 [ 3  4]
 [ 5  6]]


沿轴1广播:
[[ 1 11  2]
 [ 3 11  4]
 [ 5 11  6]]

4. numpy.delete()

  • numpy.delete()函数返回从输入数组中删除指定子数组的新数组。与insert()函数的情况一样,如果未提供轴参数,则输入数组将展开。
numpy.delete(arr, obj, axis)
# arr:输入数组。
# obj:可以被切片,整数或者整数数组,表明要从输入数组删除的子数组。
# axis:沿着它删除给定子数组的轴,如果未提供,则输入数组会被展开。
import numpy as np

a = np.arange(12).reshape(3, 4)

print('第一个数组:')
print(a)
print('\n')

print('未传递Axis参数。在插入之前输入数组会被展开。')
print(np.delete(a, 5))
print('\n')

print('删除第二列:')
print(np.delete(a, 1, axis=1))
print('\n')

print('包含从数组中删除的替代值的切片:')
a = np.array([1, 2, 3, 4, 5, 6, 7, 8, 9, 10])
print(np.delete(a, np.s_[::2]))

输出结果为:

第一个数组:
[[ 0  1  2  3]
 [ 4  5  6  7]
 [ 8  9 10 11]]


未传递Axis参数。在插入之前输入数组会被展开。
[ 0  1  2  3  4  6  7  8  9 10 11]


删除第二列:
[[ 0  2  3]
 [ 4  6  7]
 [ 8 10 11]]


包含从数组中删除的替代值的切片:
[ 2  4  6  8 10]

5. numpy.unique

  • numpy.unique()函数用于去除数组中的重复元素。
numpy.unique(arr, return_index, return_inverse, return_counts)
# arr:输入数组,如果不是一维数组则会展开。
# return_index:如果为True,返回新列表元素在旧列表中的位置(下标),并以列表形式存储。
# return_inverse:如果为True,返回旧列表元素在新列表中的位置(下标),并以列表形式存储。
# return_counts:如果为True,返回去重数组中的元素在原数组中的出现次数。
import numpy as np

a = np.array([5, 2, 6, 2, 7, 5, 6, 8, 2, 9])

print('第一个数组:')
print(a)
print('\n')

print('第一个数组的去重值:')
u = np.unique(a)
print(u)
print('\n')

print('去重数组的索引数组:')
u, indices = np.unique(a, return_index=True)
print(indices)
print('\n')

print('我们可以看到每个和原数组下标对应的数值:')
print(a)
print('\n')

print('去重数组的下标:')
u, indices = np.unique(a, return_inverse=True)
print(u)
print('\n')

print('下标为:')
print(indices)
print('\n')

print('使用下标重构原数组:')
print(u[indices])
print('\n')

print('返回去重元素的重复数量:')
u, indices = np.unique(a, return_counts=True)
print(u)
print(indices)

输出结果为:

第一个数组:
[5 2 6 2 7 5 6 8 2 9]


第一个数组的去重值:
[2 5 6 7 8 9]


去重数组的索引数组:
[1 0 2 4 7 9]


我们可以看到每个和原数组下标对应的数值:
[5 2 6 2 7 5 6 8 2 9]


去重数组的下标:
[2 5 6 7 8 9]


下标为:
[1 0 2 0 3 1 2 4 0 5]


使用下标重构原数组:
[5 2 6 2 7 5 6 8 2 9]


返回去重元素的重复数量:
[2 5 6 7 8 9]
[3 2 2 1 1 1]

下一篇:Numpy模块的学习(下)

参考教程地址:https://www.runoob.com/numpy/numpy-dtype.html
其余参考文章和教程:
https://www.w3cschool.cn/article/4618999.html
https://www.py.cn/jishu/jichu/23527.html
https://iowiki.com/numpy/numpy_index.html
https://www.5axxw.com/wiki/content/i2pltb

猜你喜欢

转载自blog.csdn.net/ungoing/article/details/127430386