第三章:NumPy (1)

木婉清2023/12/01

NumPy(1) 简介

image-2023123001

脑图连接open in new window

ndarray 对象

概述

  • 用于存放同类型元素的多维数组
numpy.array(object, dtype = None, copy = True, order = None, subok = False, ndmin = 0)
名称描述
object数组或嵌套的数列
dtype数组元素的数据类型,可选
copy对象是否需要复制,可选
order创建数组的样式,C为行方向,F为列方向,A为任意方向(默认)
subok默认返回一个与基类类型一致的数组
ndmin指定生成数组的最小维度

示例

import numpy as np

# 一维数组
a = np.array([1, 2, 3])
print(a)
运行结果

[1 2 3]

import numpy as np

# 多维数组
a = np.array([[1, 2], [3, 4]])
print(a)
运行结果

[[1 2] [3 4]]

import numpy as np

# 最小维度
a = np.array([1, 2, 3, 4, 5], ndmin=2)
print(a)
运行结果

[[1 2 3 4 5]]

import numpy as np

# dtype 参数
a = np.array([1, 2, 3], dtype=complex)
print(a)
运行结果

[1.+0.j 2.+0.j 3.+0.j]

import numpy as np

# 最小维度
a = np.array([1, 2, 3, 8, 9, 10], ndmin=3)
print(a)
运行结果

[[[1 2 3 8 9 10]]]

数据类型

常用 NumPy 基本类型

名称描述
bool_布尔型数据类型(True 或者 False)
int_默认的整数类型(类似于 C 语言中的 long,int32 或 int64)
intc与 C 的 int 类型一样,一般是 int32 或 int 64
intp用于索引的整数类型(类似于 C 的 ssize_t,一般情况下仍然是 int32 或 int64)
int8字节(-128 to 127)
int16整数(-32768 to 32767)
int32整数(-2147483648 to 2147483647)
int64整数(-9223372036854775808 to 9223372036854775807)
uint8无符号整数(0 to 255)
uint16无符号整数(0 to 65535)
uint32无符号整数(0 to 4294967295)
uint64无符号整数(0 to 18446744073709551615)
float_float64 类型的简写
float16半精度浮点数,包括:1 个符号位,5 个指数位,10 个尾数位
float32单精度浮点数,包括:1 个符号位,8 个指数位,23 个尾数位
float64双精度浮点数,包括:1 个符号位,11 个指数位,52 个尾数位
complex_complex128 类型的简写,即 128 位复数
complex64复数,表示双 32 位浮点数(实数部分和虚数部分)
complex128复数,表示双 64 位浮点数(实数部分和虚数部分)

练习

Int8 占一个字节,取值范围为:

  • 0 ~ 128
  • -128 ~ 127
  • -32768 ~ 32767
  • -128 ~ 128
答案

-128 ~ 127

Uint16 的取值范围为:

  • 0 ~ 127
  • 0 ~ 255
  • 0 ~ 65535
  • 0 ~ 4294967295
答案

0 ~ 65535

数据类型对象 dtype

用来描述与数组对应的内存区域是如何使用,它描述了数据的以下几个方面:

  • 数据的类型(整数,浮点数或者 Python 对象)
  • 数据的大小(例如, 整数使用多少个字节存储)
  • 数据的字节顺序(小端法或大端法)
numpy.dtype(object, align, copy)
名称描述
object要转换为的数据类型对象
align如果为 true ,填充字段使其类似 C 的结构体。
copy复制 dtype 对象 ,如果为 false ,则是对内置数据类型对象的引用

示例

import numpy as np
dt = np.dtype([("age", np.int8)])
print(dt)
运行结果

[('age', 'i1')]

注意

int8,int16,int32,可替换为等价的字符串 'i1','<i2','<i4',以此类推。

import numpy as np
dt = np.dtype([("age", np.int32)])
print(dt)
运行结果

[('age', '<i4')]

import numpy as np
dt = np.dtype("i8")
print(dt)
运行结果

int64

数组属性

概览

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

ndarray.shape

  • 返回一个包含数组维度的元组,可以用于调整数组大小
import numpy as np
a = np.array([[1, 2, 3], [4, 5, 6]])
print(a.shape)
运行结果

(2, 3)

import numpy as np
# a.shape 会调整数组大小
a = np.array([[1, 2, 3], [4, 5, 6]])
a.shape = (3, 2)
print(a)
运行结果

[[1 2] [3 4] [5 6]]

import numpy as np
# 使用 reshape 调整数组大小
a = np.array([[1, 2, 3], [4, 5, 6]])
b = a.reshape(3, 2)
print(b)
运行结果

[[1 2] [3 4] [5 6]]

ndarray.ndim

  • 返回数组的维数
import numpy as np
# 等间隔数字的数组
a = np.arange(0, 9, 2)
print(a)
print(a.ndim)
运行结果

[0 2 4 6 8]

1

ndarray.itemsize

  • 返回数组元素的字节单位长度
import numpy as np
# 数组的 dtype 为 int8 (一字节)
x = np.array([1, 2, 3, 4, 5], dtype=np.int8)
y = np.array([1, 2, 3, 4, 5], dtype=np.int16)
z = np.array([1, 2, 3, 4, 5], dtype=np.int32)
print(x.itemsize, y.itemsize, z.itemsize)
运行结果

1 2 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

数组创建例程

NumPy 数组创建例程

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

概览

方式说明
numpy.empty创建一个指定形状(shape)、数据类型(dtype)且未初始化的数组
numpy.zeros创建指定大小的数组,数组元素以 0 来填充
numpy.ones创建指定形状的数组,数组元素以 1 来填充

numpy.empty

  • 来创建一个指定形状(shape)、数据类型(dtype)且未初始化的数组
numpy.empty(shape, dtype = float, order = 'C')
参数描述
shape数组形状
dtype数据类型,可选
order有"C"和"F"两个选项,分别代表,行优先和列优先,在计算机内存中的存储元素的顺序。
import numpy as np
x = np.empty([3, 2], dtype=int)
print(x)
运行结果

[[744107117 760884589] [777662061 794439533] [811217005 23330817]]

注意

数组元素为随机值,因为它们未初始化

numpy.zeros

  • 创建指定大小的数组,数组元素以 0 来填充
numpy.zeros(shape, dtype = float, order = 'C')
参数描述
shape数组形状
dtype数据类型,可选
order'C' 用于 C 的行数组,或者 'F' 用于 FORTRAN 的列数组
import numpy as np
# 含有5个0的数组,默认数据类型为float
x = np.zeros(5)
y = np.zeros(5, dtype=int)
print(x)
print(y)
运行结果

[0. 0. 0. 0. 0.]

[0 0 0 0 0]

numpy.ones

  • 创建指定形状的数组,数组元素以 1 来填充
numpy.ones(shape, dtype = None, order = 'C')
参数描述
shape数组形状
dtype数据类型,可选
order'C' 用于 C 的行数组,或者 'F' 用于 FORTRAN 的列数组
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]]

NumPy 从已有的数组创建数组

  • 从已有的数组创建数组

概览

方式说明
numpy.asarray类似于 numpy.array ,常用于将 Python 序列转为 ndarray
numpy.frombuffer接受 buffer 输入参数,以流的形式读入转化成 ndarray 对象
numpy.fromiter从可迭代对象中建立 ndarray 对象,返回一维数组

numpy.asarray

  • 类似于 numpy.array ,常用于将 Python 序列转为 ndarray
numpy.asarray(a, dtype = None, order = None)
参数描述
a任意形式的输入参数,可以是,列表, 列表的元组, 元组, 元组的元组, 元组的列表,多维数组
dtype数据类型,可选
order可选,有"C"和"F"两个选项,分别代表,行优先和列优先,在计算机内存中的存储元素的顺序
import numpy as np
# 将列表转换为 ndarray
x = [1, 2, 3]
a = np.asarray(x)
print(x, type(x))
print(a, type(a))
运行结果

[1, 2, 3] <class 'list'> [1 2 3] <class 'numpy.ndarray'>

numpy.frombuffer

  • 接受 buffer 输入参数,以流的形式读入转化成 ndarray 对象
numpy.frombuffer(buffer, dtype = float, count = -1, offset = 0)
参数描述
buffer可以是任意对象,会以流的形式读入。
dtype返回数组的数据类型,可选
count读取的数据数量,默认为-1,读取所有数据。
offset读取的起始位置,默认为0。
import numpy as np 
 
s = b"Hello World!"
a = np.frombuffer(s, dtype="S1")
b = np.frombuffer(s, dtype="S2")
c = np.frombuffer(s, dtype="S3")
print(a)
print(b)
print(c)
运行结果

[b'H' b'e' b'l' b'l' b'o' b' ' b'W' b'o' b'r' b'l' b'd' b'!'] [b'He' b'll' b'o ' b'Wo' b'rl' b'd!'] [b'Hel' b'lo ' b'Wor' b'ld!']

注意

  • 前缀 u 表示该字符串是 unicode 编码
  • 前缀 b 表示该字符串是 bytes 类型
  • 前缀 f 用来格式化字符串
  • 使用 r 来表示原始字符串,这种字符串被称为“Raw String”

numpy.fromiter

  • 从可迭代对象中建立 ndarray 对象,返回一维数组
参数描述
iterable可迭代对象
dtype返回数组的数据类型
count读取的数据数量,默认为-1,读取所有数据
import numpy as np

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

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

[0. 1. 2. 3. 4.]

NumPy 数值范围数组

  • 如何从数值范围创建数组

概览

方式说明
numpy.arange使用 arange 函数创建数值范围并返回 ndarray 对象
numpy.linspace创建一个一维数组,数组是一个等差数列构成的
numpy.logspace创建一个等比数列

numpy.arange

  • 使用 arange 函数创建数值范围并返回 ndarray 对象
numpy.arange(start, stop, step, dtype)
参数描述
start起始值,默认为 0
stop终止值(不包含)
step步长,默认为 1
dtype返回 ndarray 的数据类型,如果没有提供,则会使用输入数据的类型。
import numpy as np
x = np.arange(5)
print(x)
运行结果

[0 1 2 3 4]

import numpy as np
x = np.arange(1, 100, 10, dtype=int)
print(x)
运行结果

[ 1 11 21 31 41 51 61 71 81 91]

numpy.linspace

  • 创建一个一维数组,数组是一个等差数列构成的
numpy.linspace(start, stop, num=50, endpoint=True, retstep=False, dtype=None)
参数描述
start序列的起始值
stop序列的终止值,如果 endpointtrue ,该值包含于数列中
num要生成的等步长的样本数量,默认为 50
endpoint该值为 true 时,数列中包含stop值,反之不包含,默认是 true
retstep如果为 true 时,生成的数组中会显示间距,反之不显示。
dtypendarray 的数据类型
import numpy as np
x = np.linspace(10, 20, 5)
print(x)
运行结果

[10. 12.5 15. 17.5 20. ]

import numpy as np
x = np.linspace(10, 30, 4)
print(x)
运行结果

[10. 16.66666667 23.33333333 30. ]

numpy.logspace

  • 创建一个等比数列
numpy.logspace(start, stop, num=50, endpoint=True, base=10.0, dtype=None)
参数描述
start序列的起始值为:base ** start
stop序列的终止值为:base ** stop。如果endpointtrue,该值包含于数列中
num要生成的等步长的样本数量,默认为50
endpoint该值为 true 时,数列中中包含stop值,反之不包含,默认是True。
base对数 log 的底数。
dtypendarray 的数据类型
import numpy as np
# 默认底数为 10
# 该语句的意思是:在10的1次幂到10的2次幂的闭区间中找到10个公比相同的数字
x = np.logspace(1.0, 2.0, num=10)
print(x)
运行结果

[ 10. 12.91549665 16.68100537 21.5443469 27.82559402 35.93813664 46.41588834 59.94842503 77.42636827 100. ]

import numpy as np
# 默认底数为 10
# 语句的意思是:在10的1.0次幂到10的2.0次幂的闭区间中找到10个公比相同的数字
x = np.logspace(1.0, 2.0, num=10)
print(x)
运行结果

[ 10. 12.91549665 16.68100537 21.5443469 27.82559402 35.93813664 46.41588834 59.94842503 77.42636827 100. ]

import numpy as np
# 语句的意思是:在5的1.0次幂到10的2.0次幂的闭区间中找到3个公比相同的数字
x = np.logspace(1.0, 2.0, 3, base=5)
print(x)
运行结果

[ 5. 11.18033989 25. ]

切片和索引

切片

  • ndarray对象的内容可以通过索引或切片来访问和修改,与 Pythonlist 的切片操作一样
  • ndarray 数组可以基于 0 - n 的下标进行索引,切片对象可以通过内置的 slice 函数,并设置 start , stopstep 参数进行,从原数组中切割出一个新数组
import numpy as np
# 从索引 2 开始到索引 7 停止,间隔为2
a = np.arange(10)
s = slice(2, 7, 2)
print(a[s])
运行结果

[2 4 6]

import numpy as np

a = np.arange(10)
s = slice(1, 9, 2)
print(a[s])
运行结果

[1 3 5 7]

我们也可以通过冒号分隔切片参数 start:stop:step 来进行切片操作:

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

[2 4 6]

import numpy as np
a = np.array([[5, 8, 9], [100, 300, 20], [7, 6, 3], [5, 5, 5]])
print("现在我们从索引a[2:]的地方开发切片")
print(a[2:])
print("现在我们从索引a[:3]的地方开发切片")
print(a[:3])
运行结果

现在我们从索引a[2:]的地方开发切片 [[7 6 3] [5 5 5]] 现在我们从索引a[:3]的地方开发切片 [[ 5 8 9] [100 300 20] [ 7 6 3]]

NumPy 高级索引

  • NumPy 中的高级索引指的是使用整数数组、布尔数组或者其他序列来访问数组的元素。相比于基本索引,高级索引可以访问到数组中的任意元素,并且可以用来对数组进行复杂的操作和修改。

整数数组索引

  • 使用一个数组来访问另一个数组的元素。这个数组中的每个元素都是目标数组中某个维度上的索引值。
import numpy as np
# 以下实例获取数组中 (0,0),(1,1) 和 (2,0) 位置处的元素
x = np.array([[1, 2], [3, 4], [5, 6]])
y = x[[0, 1, 2], [0, 1, 0]]
print(y)
运行结果

[1 4 5]

import numpy as np
# 以下实例获取数组中 (0,0),(1,1) 和 (2,0) 位置处的元素
x = np.array([[0, 1, 2], [3, 4, 5], [6, 7, 8], [9, 10, 11]])
rows = np.array([0, 0, 3, 3])
cols = np.array([0, 2, 0, 2])
y = x[rows, cols]
print(y)
运行结果

[ 0 2 9 11]

布尔值索引

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

# 获取大于 5 的元素
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]

import numpy as np
x = np.array([[0, 10, 12], [3, 4, 5], [6, 17, 8], [9, 0, 1]])
print(x[x >= 8])
运行结果

[10 12 17 8 9]

广播

  • 广播是指 NumPy 在算术运算期间处理不同形状的数组的能力。对数组的算术运算通常在相应的元素上进行。如果两个阵列具有完全相同的形状,这些操作就会被无缝执行。
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]

import numpy as np

a = np.array(
    [[0.0, 0.0, 0.0], [10.0, 10.0, 10.0], [20.0, 20.0, 20.0], [30.0, 30.0, 30.0]]
)
b = np.array([1.0, 2.0, 3.0])

print("第一个数组:")
print(a)
print()
print("第二个数组:")
print(b)
print()
print("第一个数组加第二个数组:")
print(a + b)
运行结果

第一个数组: [[ 0. 0. 0.] [10. 10. 10.] [20. 20. 20.] [30. 30. 30.]]

第二个数组: [1. 2. 3.]

第一个数组加第二个数组: [[ 1. 2. 3.] [11. 12. 13.] [21. 22. 23.] [31. 32. 33.]]

import numpy as np

a = np.array([[5, 8, 9], [100, 30, 20], [7, 6, 3], [5, 5, 5]])
b = np.array([0, 1, 2])
print("第一个数组加第二个数组:")
print(a + b)
运行结果

第一个数组加第二个数组: [[ 5 9 11] [100 31 22] [ 7 7 5] [ 5 6 7]]

编辑于 2024/1/4 09:33:12