栏目分类:
子分类:
返回
名师互学网用户登录
快速导航关闭
当前搜索
当前分类
子分类
实用工具
热门搜索
名师互学网 > IT > 软件开发 > 后端开发 > Python

Python | NumPy 教程(一)

Python 更新时间: 发布时间: IT归档 最新发布 模块sitemap 名妆网 法律咨询 聚返吧 英语巴士网 伯小乐 网商动力

Python | NumPy 教程(一)

Python | NumPy 教程

一、NumPy ndarray 对象

1.1 ndarray 对象简介1.2 ndarray 对象组成1.3 ndarray 对象创建 二、NumPy 数组属性三、NumPy 数据类型

3.1 常用 NumPy 基本类型3.2 数据类型对象(dtype)

3.2.1 简介3.2.2 实例化 dtype 对象 3.3 日期时间(datetime64)和时间增量(timedelta64)

3.3.1 基本日期时间

1. 简介2. ISO 8601 日期格式3. 实例 3.3.2 datetime64 和 timedelta64 运算3.3.3 工作日功能(busday)

1. busday_offset2. np.is_busday() 方法3. np.busday_count() 方法4. 自定义周掩码 3.3.4 numpy.datetime64 与 datetime.datetime 相互转换 四、NumPy 数组

4.1 NumPy 创建数组

4.1.1 numpy.empty4.1.2 numpy.zeros4.1.3 numpy.ones4.1.4 numpy.full4.1.5 numpy.eye 4.2 NumPy 从已有的数组创建数组

4.2.1 numpy.asarray4.2.2 numpy.frombuffer4.2.3 numpy.fromiter4.2.4 numpy.empty_like4.2.5 numpy.zeros_like4.2.6 numpy.ones_like4.2.7 numpy.full_like 4.3 NumPy 从数值范围创建数组

4.3.1 numpy.arange4.3.2 numpy.linspace4.3.3 numpy.logspace4.3.4 numpy.geomspace 五、NumPy 切片和索引

5.1 NumPy 索引5.2 NumPy 切片

5.2.1 slice 函数5.2.2 冒号分隔 5.3 NumPy 高级索引

5.3.1 整数数组索引5.3.2 布尔索引5.3.3 花式索引 六、NumPy 广播(Broadcast)七、NumPy 遍历数组

7.1 普通迭代7.2 nditer 多维迭代器

7.2.1 基本使用7.2.2 order 参数:指定访问元素的顺序7.2.3 op_flags 参数:迭代时修改元素的值7.2.4 flags 参数

1.外部循环 flags=['external_loop']2.追踪索引:flags=['c_index']、flags=['f_index']、flags=['multi_index']
qquad Numpy 是 Python 中科学计算的核心库,NumPy 这个词来源于 Numerical 和 Python 两个单词。它提供了一个高性能的多维数组对象,以及大量的库函数和操作,可以帮助程序员轻松地进行数值计算,广泛应用于机器学习模型、图像处理和计算机图形学、数学任务等领域。

一、NumPy ndarray 对象 1.1 ndarray 对象简介

NumPy 最重要的一个特点是其 N 维数组对象 ndarray,它是一系列同类型数据的集合,以 0 下标为开始进行集合中元素的索引。ndarray 对象是用于存放同类型元素的多维数组。ndarray 中的每个元素在内存中都有相同存储大小的区域。 1.2 ndarray 对象组成

一个指向数据(内存或内存映射文件中的一块数据)的指针。数据类型或 dtype,描述在数组中的固定大小值的格子。一个表示数组形状(shape)的元组,表示各维度大小的元组。一个跨度元组(stride),其中的整数指的是为了前进到当前维度下一个元素需要"跨过"的字节数。

跨度可以是负数,这样会使数组在内存中后向移动,切片中 obj[::-1] 或 obj[:,::-1] 就是如此。 1.3 ndarray 对象创建

创建一个 ndarray 只需调用 NumPy 的 array 函数即可:

numpy.array(object, dtype = None, copy = True, order = None, subok = False, ndmin = 0)
参数说明:

object:数组或嵌套的序列。dtype:数组元素的数据类型,可选。copy:对象是否需要复制,是否生成副本,可选。

import numpy as np

a = np.array([1, 2, 3])
b = np.array(a, copy=True)
a[0] = 0

print(a) # [0 2 3]
print(b) # [1 2 3]

可以看到 a 和 b 的值不同,说明 b 是 a 的副本,两个是不同的对象。 order:指定数组在计算机内存中的存储元素的顺序。C为行方向(默认),F为列方向,A 为原型数组在内存中存储的原顺序,K 为元素在内存中的出现顺序。subok:默认返回一个与基类类型一致的数组。示例:基类类型是

import numpy as np

mat = np.matrix('1 2 7; 3 4 8; 5 6 9')
print(type(mat))
print(mat)
matT = np.array(mat, subok=True)
matF = np.array(mat, subok=False)
print(type(matT))
print(type(matF))
ndmin:指定生成数组的最小维度。 二、NumPy 数组属性

ndarray.ndim:秩,即轴的数量或维度的数量。

numpy 数组的维数称为秩(rank),秩就是轴(axis)的数量,即数组的维度,一维数组的秩为 1,二维数组的秩为 2,以此类推。 ndarray.shape:数组的维度。

返回一个元组,这个元组的长度就是维度的数目,即 ndim 属性(秩)。例:对于矩阵,n行m列,返回 (n,m)。 ndarray.size:数组元素的总个数。ndarray.dtype:ndarray 对象的元素类型。ndarray.nbytes:总字节数。ndarray.strides:由每个维度的字节跨度组成的元组。

示例:整数类型占用 4 个字节。

import numpy as np

ls = [[[1, 2, 3, 4], [5, 6, 7, 8], [9, 10, 11, 12]], 
      [[13, 14, 15, 16], [17, 18, 19, 20], [21, 22, 23, 24]]]
a = np.array(ls, dtype=int)
print(a)
print(a.strides)
可以利用 strides 属性获取元素偏移量:假设数组 arr 是三维数组,那么arr[i][j][k] 的偏移量为:offset = arr.strides[0]*i + arr.strides[1]*j + arr.strides[2]*k ndarray.itemsize:ndarray 对象中每个元素的大小,以字节为单位。

例如:一个元素类型为 float64 的数组 itemsize 属性值为 8(float64占用64个bits,每个字节长度为8,所以64/8,占用8个字节) ndarray.base:若一个数组存在基类数组,用 base 可获取基类数组。ndarray.flags:ndarray 对象的内存信息,有关数组内存布局的信息。包含以下属性:

C_ConTIGUOUS (C):指的是数组的行存储在内存中的地址是连续的。F_ConTIGUOUS (F):指的是数组的列存储在内存中的地址是连续的。OWNDATA (O):是否是数据的所有者。WRITEABLE (W):数据区域可以被写入,将该值设置为 False,则数据为只读ALIGNED (A):数据和所有元素都适当地对齐到硬件上。WRITEBACKIFCOPY:UPDATeIFCOPY 已弃用,由 WRITEBACKIFCOPY 取代。UPDATEIFCOPY (U):这个数组是其它数组的一个副本,当这个数组被释放时,原数组的内容将被更新。 ndarray.real:ndarray元素的实部。ndarray.imag:ndarray 元素的虚部。ndarray.data:包含实际数组元素的缓冲区,由于一般通过数组的索引获取元素,所以通常不需要使用这个属性。 三、NumPy 数据类型

qquad NumPy 支持比 Python 更多种类的数值类型,下表所列的数据类型都是 NumPy 内置的数据类型,为了区别于 Python 原生的数据类型,bool、int、float、complex、str 等类型名称末尾都加了 _。

qquad print(numpy.dtype) 所显示的都是 NumPy 中的数据类型,而非 Python 原生数据类型。

3.1 常用 NumPy 基本类型

bool_:布尔型数据类型(True 或者 False)。字符代码:b。int_:默认的整数类型(类似于 C 语言中的 long,int32 或 int64)。intc:与 C 的 int 类型一样,一般是 int32 或 int 64。intp:用于索引的整数类型(类似于 C 的 ssize_t,一般情况下仍然是 int32 或 int64)。int8 / byte:字节(-128 to 127)。字符代码:i1。int16 / short:整数(-32768 to 32767)。字符代码:i2。int32 / intc / int_ / long:整数(-2147483648 to 2147483647)。字符代码:i4。int64 / longlong / intp / int0:整数(-9223372036854775808 to 9223372036854775807)。字符代码:i8。uint8 / ubyte:无符号整数(0 to 255)。字符代码:u1。uint16 / ushort:无符号整数(0 to 65535)。字符代码:u2。uint32 / uintc:无符号整数(0 to 4294967295)。字符代码:u4。uint64 / ulonglong / uintp / uint0:无符号整数(0 to 18446744073709551615)。字符代码:u8。float16 / half:半精度浮点数,包括:1 个符号位,5 个指数位,10 个尾数位。字符代码:f2。float32 / single:单精度浮点数,包括:1 个符号位,8 个指数位,23 个尾数位。字符代码:f4。float64 / float_ / double:双精度浮点数,包括:1 个符号位,11 个指数位,52 个尾数位。字符代码:f8。complex64 / singlecomplex:复数,表示双 32 位浮点数(实数部分和虚数部分)。字符代码:c8。complex128 / complex_ / cfloat / cdouble / longcomplex / clongfloat / clongdouble:复数,表示双 64 位浮点数(实数部分和虚数部分)。字符代码:c16。unicode_ / unicode / str_ / str0:表示 Unicode 字符串。字符代码:U。U 后带数字表示字符串长度,超出部分将被截断,例:U20。string_:表示字节串类型。字符代码:S / a。只能包含 ASCII 码字符,S 或 a 后带数字表示字节串长度,超出部分将被截断,例:S20、a10。datetime64:NumPy 1.7 开始支持的日期时间类型。字符代码:M,例:M8[D],必须要填写单位。timedelta64:表示两个时间之间的间隔。字符代码:m。 3.2 数据类型对象(dtype) 3.2.1 简介

数据类型对象 dtype 是用来描述与 ndarray 数组对应的内存区域如何使用,这依赖如下几个方面:

数据的类型(整数,浮点数或者 Python 对象)。数据的大小(例如: 整数使用多少个字节存储)。数据的字节顺序(小端法"<“或大端法”>",大端法高字节在前低字节在后,小端法低字节在前高字节在后)。在结构化类型的情况下,字段的名称、每个字段的数据类型和每个字段所取的内存块的部分。如果数据类型是子数组,它的形状和数据类型字节顺序是通过对数据类型预先设定"<“或”>"来决定的。 3.2.2 实例化 dtype 对象

dtype 对象构造语法:numpy.dtype(obj, align=False, copy=False)

object:要转换为数据类型对象的对象。align:如果为 True,填充字段使其类似 C 的结构体,只有当 object 是字典或逗号分隔的字符串时才可以是 True。copy:复制 dtype 对象,如果为 False,则是对内置数据类型对象的引用。 实例:定义一个结构化数据类型 student,包含字符串字段 name,整数字段 age,并将这个 dtype 应用到 ndarray 对象。

import numpy as np
student = np.dtype([('name', 'S20'), ('age', 'i1')])
print(student)

a = np.array([('tom', 21), ('Jerry', 18)], dtype = student)
print(a)

本案例中 S20 表示字节串长度为 20,所以只能输入 ASCII 字符,输出中带有 b。 3.3 日期时间(datetime64)和时间增量(timedelta64)

qquad 从NumPy 1.7开始,有些核心数组数据类型本身支持日期时间功能。数据类型称为 “datetime64”,之所以这样命名是因为 Python 中包含的 datetime 库已经采用了 “datetime”。

3.3.1 基本日期时间 1. 简介

创建日期时间的最基本方法是使用 ISO 8601日期(2022-03-07)或日期时间(2022-03-07T21:38:13)格式的字符串。也可以通过相对于 Unix 纪元(1970 年 1 月 1 日 00:00:00 UTC)的偏移量从整数创建日期时间。datetime64 可以指定使用的单位,单位包括年(‘Y’),月(‘M’),周(‘W’)和天(‘D’),而时间单位是小时(‘h’),分钟(‘m’) ),秒(‘s’),毫秒(‘ms’),微秒(‘us’),纳秒(‘ns’),皮秒(‘ps’),飞秒(‘fs’),阿托秒(‘as’),其中秒、毫秒、微秒、纳秒、皮秒、飞秒、阿托秒每两级之间的换算进率为1000。

周(‘W’)是一个比较奇怪的单位,当用 ’W’ 去指定 D 类型的 datetime64 变量时,有如下规定:
1)如果是星期四,返回当天;
2)否则,返回上一个星期四的日期。 datetime64 数据类型还接受字符串 “NAT”(小写/大写字母的任意组合)作为“Not A Time”值。 2. ISO 8601 日期格式

ISO 8601 日期格式:YYYY-MM-DDThh:mm:ss[.mmm]TZD。样例:2022-03-07T21:38:13表示中国标准时间2022年3月7日21:38:13。

YYYY:表示四位数的年份。MM:表示两位数的月份,从 01 到 12。DD:表示两位数的天,从 01 到 31。T:指示时间元素的开始字符。hh:表示两位数的小时,从 00 到 23,不包括 AM/PM。mm:表示两位数的分钟,从 00 到 59。ss:表示两位数的秒,从 00 到 59。mmm:表示三位数的毫秒数,从 000 到 999。TZD:表示时区指示符:Z 或 +hh:mm 或 -hh:mm,+ 或 - 表示时区距离 UTC(世界标准时间)的时差。如果时间在零时区,并恰好与协调世界时(UTC)相同,那么在时间最后加一个大写字母 Z。例:CST(中国标准时间):UTC+08:00;EST(北美东部标准时间):UTC-05:00。 3. 实例

创建日期时间,通过相对于 Unix 纪元(1970 年 1 月 1 日 00:00:00 UTC)的偏移量从整数创建日期时间。

np.datetime64(10, 'Y')
创建日期时间,自动选择对应单位。
import numpy as np

a = np.datetime64('2022')
print(a,a.dtype)

b = np.datetime64('2022-03')
print(b,b.dtype)

c = np.datetime64('2022-03-07')
print(c,c.dtype)

d = np.datetime64('2022-03-07 21')
print(d,d.dtype)

e = np.datetime64('2022-03-07 21:38')
print(e,e.dtype)

f = np.datetime64('2022-03-07 21:38:13')
print(f,f.dtype)
创建日期时间,指定单位。
import numpy as np
a = np.datetime64('2022-03','s')
print(a)
print(np.datetime64('2022-03') == np.datetime64('2022-03-01'))

由上例可以看出,2022-03 和 2022-03-01 所表示的其实是同一个时间。事实上,如果两个 datetime64 对象具有不同的单位,它们可能仍然代表相同的时刻。并且从较大的单位(如月份)转换为较小的单位(如天数)是安全的。 字符串创建日期时间数组(详尽效应):如果 list 中单位不统一,则统一用最详尽的方式表示日期(详尽效应)。

import numpy as np
a = np.array(['2022-03', '2022-03-07 21:38','2022-03-07 21:38:13'], dtype='datetime64')
print(a)
print(a.dtype)
配合 arange 函数,用于生成日期范围。
import numpy as np
a = np.arange('2022-03', '2022-04', dtype='datetime64[D]')
print(a)
配合 arange 函数时可以设置间隔。
import numpy as np
a = np.arange('2022-02', '2022-03', dtype='datetime64[6D]')
b = np.arange('2022-03-07', '2022-03-08', dtype='datetime64[3h]')
print(a)
print(b)
3.3.2 datetime64 和 timedelta64 运算

qquad NumPy允许将两个Datetime值相减,该操作会产生一个带有时间单位的数字。由于NumPy的核心没有物理量系统,因此创建了timedelta64数据类型以补充 datetime64。timedelta64 表示两个 datetime64 之间的差。timedelta64 也是带单位的,例如:(D)ay,(M)onth,(Y)ear,(h)ours,(m)inutes 或(s)econd,并且和相减运算中的两个 datetime64 中的较小的单位保持一致。(详尽效应)timedelta64 数据类型还接受字符串 “NAT” 代替 “Not A Time” 值的数字。

实例:

import numpy as np

a = np.datetime64('2022-03-07') - np.datetime64('2022-03-07')
b = np.datetime64('2022-03-07') - np.datetime64('2022-03-07 08:00')
c = np.datetime64('2022-03-07') - np.datetime64('2022-03-07 23:00', 'D')
d = np.datetime64('2022-03-07') + np.timedelta64(20, 'D')
# 单独运算
e = np.timedelta64(1, 'Y')
f = np.timedelta64(6, 'M')

print(a, a.dtype)
print(b, b.dtype)
print(c, c.dtype)
print(d, d.dtype)
print(e, e.dtype)
print(f, f.dtype)
print(e+f)
print(6*f)
有两个 timedelta 单位(“ Y”,年和 “M”,月)被特别处理,因为它们表示多少时间取决于使用时间。尽管 timedelta 天(“D”)单位等于 24 小时,但无法将一个月单位转换为天,因为不同的月份有不同的天数。示例如下:
a = np.timedelta64(1, 'Y')
np.timedelta64(a, 'M')
np.timedelta64(a, 'D')
3.3.3 工作日功能(busday)

qquad busday 默认周一至周五是工作日。该实现基于一个 weekmask,包含 7 个布尔标志,用于工作日。

1. busday_offset

busday_offset将指定的偏移量应用于工作日,单位天(‘D’)。如果当前日期为非工作日,则默认是报错的,可以指定roll=‘forward’或 roll=‘backward’规则来避免报错(注:forward 指的是日历向后,backward 指的是日历向前,如果从字面意思容易弄混)。当输出日期落在周末或假日时, busday_offset会将日期滚动到有效的工作日,然后输出。示例:

import numpy as np

print(np.busday_offset('2022-03-07', 3)) # 2022-03-07 周一
print(np.busday_offset('2022-03-07', 5)) # 向后滚动5天是周六,会继续滚动到有效的工作日
print(np.busday_offset('2022-03-06', 3)) # 2022-03-06 周日,会报错
print(np.busday_offset('2022-03-06',3,roll='forward')) # 指定roll='forward'
2. np.is_busday() 方法

np.is_busday() 方法返回指定日期是否是工作日。示例:

import numpy as np

print(np.is_busday(np.datetime64('2022-03-07'))) # 2022-03-07 周一
print(np.is_busday('2022-03-07'))
print(np.is_busday(np.datetime64('2022-03-06'))) # 2022-03-06 周日
print(np.is_busday('2022-03-06'))
3. np.busday_count() 方法

np.busday_count() 方法返回两个日期之间的工作日数量。示例:

import numpy as np

print(np.busday_count(np.datetime64('2022-03-07'),np.datetime64('2022-04-07'))) # 输出 23
print(np.busday_count('2022-03-07','2022-04-07')) # 输出 23
实例:统计一个 datetime64[D] 数组中的工作日天数,使用 numpy.count_nonzero 方法计算数组中非零值的数量。
import numpy as np

begindates = np.datetime64('2022-03-07')
enddates = np.datetime64('2022-04-07')

a = np.arange(begindates, enddates, dtype='datetime64')
print(a)

b = np.count_nonzero(np.is_busday(a))
print(b)

c = np.busday_count(begindates, enddates)
print(c)

a 和 b 的组合效果等于 c,都是在计算一段日期范围的工作日天数,且前闭后开。 4. 自定义周掩码

自定义周掩码值,即指定一周中哪些星期是工作日。方式如下:

weekmask = [1, 1, 1, 1, 0, 1, 0]weekmask = “1111100”weekmask = “Mon Tue Wed Thu Fri” 实例:

import numpy as np

print(np.is_busday('2022-03-07', weekmask=[1, 0, 1, 0, 1, 1, 0])) # 2022-03-07 周一工作日
print(np.is_busday('2022-03-07', weekmask='0110110')) # 2022-03-07 周一非工作日
print(np.is_busday('2022-03-07', weekmask='Mon Tue Wed Thu Fri')) # 2022-03-07 周一(Mon)工作日
3.3.4 numpy.datetime64 与 datetime.datetime 相互转换
import numpy as np
import datetime

dt = datetime.datetime(2022, 3, 7)
dt64 = np.datetime64(dt, 'D') # 转换datetime对象
print(dt64, dt64.dtype)

dt2 = dt64.astype(datetime.datetime) # 转换 numpy.datetime64 对象
print(dt2)

四、NumPy 数组 4.1 NumPy 创建数组

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

4.1.1 numpy.empty

numpy.empty 方法用来创建一个指定形状(shape)、数据类型(dtype)且未初始化的数组(数组元素为随机值):

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

shape:数组形状,必选。dtype:数据类型,可选。默认为浮点数。order:默认"C",可选。有"C"和"F"两个选项,分别代表行优先和列优先,在计算机内存中的存储元素的顺序。 4.1.2 numpy.zeros

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

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

shape:数组形状,必选。dtype:数据类型,可选。默认为浮点数。order:默认"C",可选。有"C"和"F"两个选项,分别代表行优先和列优先,在计算机内存中的存储元素的顺序。 4.1.3 numpy.ones

创建指定形状的数组,数组元素以 1 来填充:

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

shape:数组形状,必选。dtype:数据类型,可选。默认为浮点数。order:默认"C",可选。有"C"和"F"两个选项,分别代表行优先和列优先,在计算机内存中的存储元素的顺序。 4.1.4 numpy.full

创建指定维度和类型的数组,填充 fill_value。

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

shape:数组形状,必选。fill_value:填充值,必选。dtype:数据类型,可选。默认为 None。order:默认"C",可选。有"C"和"F"两个选项,分别代表行优先和列优先,在计算机内存中的存储元素的顺序。 4.1.5 numpy.eye

创建对角线元素全为 1,其余元素全为 0 的矩阵。

numpy.ones(N, M = None, k = 0, dtype = float, order = 'C')

N:如果 M 没有传值,表示要创建一个行列数都为 N 的二维数组;如果 M 传值,N 表示要创建的二维数组的行数。M:表示要创建的二维数组的列数。k:表示从第 1 行开始的对角线起始位置,默认是 0,表示从左上角第 1 个元素开始。 4.2 NumPy 从已有的数组创建数组 4.2.1 numpy.asarray

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

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

a:任意形式的输入参数,可以是,列表, 列表的元组, 元组, 元组的元组, 元组的列表,多维数组。dtype:数据类型,可选。order:默认"C",可选。C为行方向(默认),F为列方向,A 为原型数组在内存中存储的原顺序,K 为元素在内存中的出现顺序。 4.2.2 numpy.frombuffer

numpy.frombuffer 接受 buffer 输入参数,以流的形式读入转化成 ndarray 对象。

numpy.frombuffer(buffer, dtype = float, count = -1, offset = 0)

buffer:实现了 __buffer__ 方法的对象。dtype:返回数组的数据类型count:读取的数据数量,默认为 -1,读取所有数据。offset:读取的起始位置,默认为 0。 4.2.3 numpy.fromiter

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

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

iterable:实现了 __iter__方法的可迭代对象。如:字符串、列表、元组、集合、字典等等之类的对象都属于可迭代对象。dtype:返回数组的数据类型,必选。count:读取的数据数量,默认为 -1,读取所有数据。 4.2.4 numpy.empty_like

numpy.empty_like 方法返回一个与给定数组具有相同维度和类型的未初始化的新数组。

numpy.empty_like(prototype, dtype=None, order='K', subok=True)

prototype:给定的数组。dtype:返回数组的数据类型,默认值 None,则使用给定数组的类型order:指定阵列的内存布局,默认 K。C为行方向(默认),F为列方向,A 为原型数组在内存中存储的原顺序,K 为元素在内存中的出现顺序。subok:如果为 True,那么新创建的数组将成为原型的子类,否则它将是 base-class 数组。默认为 True。 4.2.5 numpy.zeros_like

numpy.zeros_like 方法返回一个与给定数组具有相同维度和类型的以 0 来填充的新数组。

numpy.zeros_like(a, dtype=None, order='K', subok=True)
参数同上。 4.2.6 numpy.ones_like

numpy.ones_like 方法返回一个与给定数组具有相同维度和类型的以 1 来填充的新数组。

numpy.ones_like(a, dtype=None, order='K', subok=True)
参数同上。 4.2.7 numpy.full_like

numpy.full_like 方法返回一个与给定数组具有相同维度和类型的以 fill_value 来填充的新数组。

numpy.full_like(a, fill_value, dtype=None, order='K', subok=True)

a:给定的数组。fill_value:填充值。dtype:返回数组的数据类型,默认值 None,则使用给定数组的类型order:指定阵列的内存布局,默认 K。C为行方向,F为列方向,A 为原型数组在内存中存储的原顺序,K 为元素在内存中的出现顺序。subok:如果为 True,那么新创建的数组将成为原型的子类,否则它将是 base-class 数组。默认为 True。 4.3 NumPy 从数值范围创建数组 4.3.1 numpy.arange

numpy 包中的 arange 函数根据 start 与 stop 指定的范围以及 step 设定的步长,生成一个 ndarray 对象并返回。格式如下:

numpy.arange(start, stop, step, dtype)

start:起始值,默认为 0。stop:终止值(不包含)。step:步长,默认为1。dtype:返回 ndarray 的数据类型。 4.3.2 numpy.linspace

numpy.linspace 函数用于创建一个一维数组,数组是一个等差数列构成的,格式如下:

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

start:序列的起始值。stop:序列的终止值,如果 endpoint 为 true,该值包含于数列中。num:要生成的等步长的样本数量,默认为 50。endpoint:该值为 True 时,数列中包含 stop 值,反之不包含,默认是 True。

该值为 False 时,num + 1 个值在 endpoint 的间隔中间隔开,返回除最后一个 endpoint 外的所有值。实例:

import numpy as np

a = np.linspace(0, 10, 5, endpoint=True, retstep=True)
print(a)
b = np.linspace(0, 10, 5, endpoint=False, retstep=True)
print(b)
retstep:如果为 True 时,生成的数组中会显示间距,反之不显示。
import numpy as np

a = np.linspace(0, 10, 5, retstep=True)
print(a)
dtype:返回 ndarray 的数据类型。 4.3.3 numpy.logspace

numpy.logspace 函数用于创建一个于等比数列。格式如下:

np.logspace(start, stop, num=50, endpoint=True, base=10.0, dtype=None)

start:序列的起始值为: base s t a r t base^{start} basestartstop:序列的终止值为: base s t o p base^{stop} basestop。如果 endpoint 为 True,该值包含于数列中。sqnum:要生成的等步长的样本数量,默认为 50。endpoint:该值为 True 时,数列中中包含 stop 值,反之不包含,默认是 True。base:对数 log 的底数,默认底数是 10。dtype:返回 ndarray 的数据类型。 4.3.4 numpy.geomspace

numpy.geomspace 函数返回数字以对数刻度(几何级数)均匀分布。这类似于 logspace,但是直接指定了端点。每个输出样本是前一个样本的恒定倍数。格式如下:

numpy.geomspace(start, stop, num=50, endpoint=True, dtype=None, axis=0)

start:序列的起始值。stop:序列的终止值。

start 与 stop 可以是符合广播条件的数组。(下文讲解 numpy 广播) num:要生成的等步长的样本数量,默认为 50。endpoint:该值为 Ture 时,数列中中包含 stop 值,反之不包含,默认是 True。dtype:返回 ndarray 的数据类型。axis:默认axis = 0。仅当 start 或 stop 为数组/元组时才有用。

特别注意:numpy.geomspace 返回数组的维度会在 start 与 stop 维度基础上+1,新增维度的值为 num !假设输入数组维度为 n,则输出数组维度为 n+1,axis = i,则在输出数组的第 i 个索引处为新增的维度,含有 num 个值(i不可以大于输出数组的维度,且最后一个维度可以使用-1获取)。实例:输入 2 维数组,返回 3 维数组。当 axis=0 时,返回形状为 (5,2,3) 的数组;当 axis=1 时,返回形状为 (2,5,3) 的数组;当 axis=2 时,返回形状为 (2,3,5) 的数组.

np.geomspace([[1,2,3],[4,5,6]],[[10,20,30]],num=5,axis=0)
np.geomspace([[1,2,3],[4,5,6]],[[10,20,30]],num=5,axis=1)
np.geomspace([[1,2,3],[4,5,6]],[[10,20,30]],num=5,axis=2)
五、NumPy 切片和索引

qquad ndarray 对象的内容可以通过索引或切片来访问和修改,与 Python 中 list 的切片操作一样。

5.1 NumPy 索引

ndarray 数组可以基于 0 - n 的下标进行索引。 5.2 NumPy 切片 5.2.1 slice 函数

python 内置函数 slice 可以用来构造 slice 对象,slice 对象用于指定如何对序列进行裁切。格式如下:

slice(start, end, step)

start:可选。整数,指定在哪个位置开始裁切。默认为 0。end:可选。整数,指定在哪个位置结束裁切。step:可选。整数,指定裁切的步长。默认为 1。 实例:通过 arange() 函数创建 ndarray 对象。 然后,分别设置起始、终止和步长的参数为 2、7 和 2。

import numpy as np

a = np.arange(10)
s = slice(2,7,2)
print (a[s])
切片可以使用省略号“…”,如果在行位置使用省略号,那么返回值将包含所有行元素,反之,则包含所有列元素。示例如下:
import numpy as np

a = np.array([[1,2,3],[3,4,5],[4,5,6]]) # 创建a数组
print("a[...]:n",a[...]) # 返回整个数组
print ("a[...,1]:n",a[...,1]) # 返回数组的第二列
print ("a[1,...]:n",a[1,...]) # 返回数组的第二行
print ("a[...,1:]:n",a[...,1:]) # 返回第二列(包含)后的所有列
5.2.2 冒号分隔

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

start:可选。整数,指定在哪个位置开始裁切。默认为 0。

如果只放置 start 一个参数,将返回 start 索引相对应的单个元素。如果为 [start:],表示 start 索引开始以后的所有项都将被提取。 end:可选。整数,指定在哪个位置结束裁切。step:可选。整数,指定裁切的步长。默认为 1。 5.3 NumPy 高级索引

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

5.3.1 整数数组索引

使用 N 维整数数组索引来获取 N 维数组中的元素( N ≥ 2 Ngeq2 N≥2),N 维整数数组中的数值表示该维度的下标值。实例 1: 使用 2 维整数数组索引[[0,1,2], [0,1,0]]获取 2 维数组中(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)
实例 2:获取了 4*3 数组中的四个角上元素,它们对应的行索引是 [0,0] 和 [3,3],列索引是 [0,2] 和 [0,2]。
import numpy as np
b = np.array([[ 0, 1, 2],
              [ 3, 4, 5],
              [ 6, 7, 8],
              [ 9,10,11]])
r = np.array([[0,0],[3,3]])
c = np.array([[0,2],[0,2]])
#获取四个角的元素
c = b[r,c]
print(c)
实例 3:可以将切片所使用的:或省略号...与整数数组索引结合使用,示例如下:
import numpy as np
arr = np.array([[ 0,  1,  2],
              [ 3,  4,  5],
              [ 6,  7,  8],
              [ 9, 10, 11]])

a = arr[1:4,1:3] # 对行列分别进行切片
print("a:n",a)
b = arr[1:4,[1,2]]# 对行使用基础索引,对列使用高级索引
print("b:n",b)
c = arr[...,1:]# 对行使用省略号
print("c:n",c)
5.3.2 布尔索引

当输出的结果需要经过布尔运算(如:比较运算)时,此时会使用到另一种高级索引方式,即布尔数组索引。实例 1:返回数组中大于 6 的的所有元素。

import numpy as np

x = np.array([[ 0,  1,  2],[ 3,  4,  5],[ 6,  7,  8],[ 9, 10, 11]])
print(x[x > 6]) # [ 7  8  9 10 11]
实例 2:使用补码运算符去除 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.]
5.3.3 花式索引

花式索引根据索引数组的值作为目标数组的某个轴的下标来取值。花式索引会生成一个新的副本。实例 1:当原数组是一维数组时,使用一维整型数组作为索引,那么索引结果就是相应索引位置上的元素。

import numpy as np
arr = np.array([1,2,3,4])
print(arr[1]) # 2
实例 2:当原数组是二维数组时,索引数组也需要是二维的,索引数组的元素值与被索引数组的每一行相对应。
import numpy as np
arr  = np.arange(32).reshape((8,4))
print(arr, "n")
# 分别对应第 4 行数据、第 2 行数据、第 1 行数据、第 7 行数据项
print(arr[[4,2,1,7]])
实例 3:可以使用倒序索引数组。
import numpy as np
arr = np.arange(32).reshape((8,4))
print(arr, "n")
print(arr[[-4,-2,-1,-7]])
实例 4:可以同时使用多个索引数组,但这种情况下需要添加 np.ix_。
import numpy as np
arr = np.arange(32).reshape((8,4))
print(arr, "n")
print(arr[np.ix_([1,5,7,2],[0,3,1,2])])

如图所示,[1,5,7,2] 代表行索引,而 [0,3,1,2] 表示与行索引相对应的列索引,也就是行中的元素值会按照列索引值排序。比如:第一行元素,未排序前的顺序是 [4,5,6,7],经过列索引排序后变成了 [4,7,5,6]。 六、NumPy 广播(Broadcast)

广播(Broadcast)是 numpy 对不同形状(shape)数组进行数值计算的方式,数组的算术运算通常在相对应位置上的元素之间进行。广播时需要对两个数组做广播机制处理,不是所有情况下两个数组都能进行广播机制的处理,有要求即两数组需满足广播兼容,需判断两个数组能否进行广播机制处理成同型shape的数组然后广播。判断是否广播兼容,规则是,比较两个数组的shape,从shape的尾部开始一一比对。广播的规则:

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

数组 a 和 b 的第一维分别为 4 和 1,将数组 b 扩展为 4,即将 [1, 2, 3] 复制 4 次。

import numpy as np 
 
a = np.array([[ 0, 0, 0],
           [10,10,10],
           [20,20,20],
           [30,30,30]])
b = np.array([1,2,3])
print(a + b)
实例 2:数组 a 的形状为 (4,3),数组 b 的形状为 (1,3),数组 a 和 b 进行加法运算。(数组 b 在二维上重复 4 次再运算)
import numpy as np 
 
a = np.array([[ 0, 0, 0],
              [10,10,10],
              [20,20,20],
              [30,30,30]])
b = np.array([1,2,3])
c = np.tile(b,(4,1))  
print("cn",c)
print("a+cn",a+c)

np.tile(a,(x,y)) 把数组 a 在行上重复 x 次,在列上重复 y 次。括号中也可以有多个数字,表示扩展到多维。

arr = np.array([6,8,9])
np.tile(arr,(3,4,5))
七、NumPy 遍历数组 7.1 普通迭代

ndarray 的普通迭代跟 Python 及其他语言中的迭代方式无异,N 维数组,就要用 N 层的 for 循环。实例:遍历二维数组。

import numpy as np

ls = [[1, 2], [3, 4], [5, 6]]
a = np.array(ls, dtype=int)
for row in a:
    for cell in row:
        print(cell,end=",")
7.2 nditer 多维迭代器 7.2.1 基本使用

NumPy 提供了一个 nditer 迭代器对象,它可以配合 for 循环完成对数组元素的遍历。实例:使用 arange() 函数创建一个 3*4 数组,并使用 nditer 生成迭代器对象。

import numpy as np
a = np.arange(1,13)
a = a.reshape(3,4)
print(a)
# 使用nditer迭代器,并使用for进行遍历
for x in np.nditer(a):
    print(x,end=",")
7.2.2 order 参数:指定访问元素的顺序

在内存中,Numpy 数组提供了两种存储数据的方式,分别是 C-order(行优先顺序)与 Fortrant-order(列优先顺序),默认是行优先顺序。可以通过 nditer 对象的 order 参数来指定访问元素的顺序。默认以内存中元素的顺序(order=‘K’),即创建 ndarray 时指定的顺序。

for x in np.nditer(a, order='F'):Fortran order,即是列序优先;for x in np.nditer(a.T, order='C'):C order,即是行序优先。 实例:分别以行序优先和列序优先输出数组 a。

import numpy as np
 
a = np.arange(1,13)
a = a.reshape(3,4)
print('原始数组是:') 
print(a) 
print('n以 C 风格顺序排序:')
for x in np.nditer(a,order="C"):  
    print(x,end="," )
print('n以 F 风格顺序排序:')
for x in np.nditer(a,order="F"):  
    print(x,end="," )
需要注意的一个重要问题是,顺序的选择是为了匹配数组的内存布局,这样做是为了提高访问效率,我们可以通过迭代一个数组的转置来了解这一点。
import numpy as np

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

print("原数组:n",a)
for x in np.nditer(a):
    print(x,end=",")
    
print("n转置(内存布局不变):n",a.T)    
for x in np.nditer(a.T):
    print(x,end=",")
    
print("n转置(内存重新布局):n",a.T.copy())    
for x in np.nditer(a.T.copy()):
    print(x,end=",")

a 和 a.T 的遍历顺序是一样的,也就是他们在内存中的存储顺序也是一样的,但是 a.T.copy() 的遍历结果是不同的,那是因为它和前两种的存储方式是不一样的,默认是按行访问。 7.2.3 op_flags 参数:迭代时修改元素的值

nditer 对象提供了一个可选参数 op_flags,它表示能否在遍历数组时对元素进行修改。它提供了三种模式,如下所示:

readonly(默认):只读模式,遍历时不能修改数组中的元素。readwrite:读写模式,遍历时可以修改元素值。writeonly:只写模式,遍历时可以修改元素值。 实例:将 nditer 对象的 op_flags 参数设置为 readwrite,修改 a 数组元素值。

import numpy as np
 
a = np.arange(1,13) 
a = a.reshape(3,4)  
print('原始数组是:')
print(a)
for x in np.nditer(a,op_flags=['readwrite']): 
    x[...] = x * 10
print('修改后的数组是:')
print(a)
7.2.4 flags 参数 1.外部循环 flags=[‘external_loop’]

当指定 flags=[‘external_loop’] 时,将返回一维数组而并非单个元素。具体来说,当 ndarray 的存储顺序和遍历顺序一致时,将所有元素组成一个一维数组返回;当 ndarray 的存储顺序和遍历顺序不一致时,返回每次遍历的一维数组。实例 1:ndarray 的存储顺序和遍历顺序一致时,将所有元素组成一个一维数组返回。

import numpy as np

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

print("原数组:n",a)
for x in np.nditer(a,flags=['external_loop']):
    print(x,end=",")
实例 2:ndarray 的存储顺序和遍历顺序不一致时,返回每次遍历的一维数组。
import numpy as np

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

print("原数组:n",a)
for x in np.nditer(a,flags=['external_loop'],order='F'):
    print(x,end=",")
2.追踪索引:flags=[‘c_index’]、flags=[‘f_index’]、flags=[‘multi_index’]

c_index:跟踪 C 顺序索引。示例如下:

import numpy as np

a = np.arange(24).reshape(2, 3, 4)
print(a)
it = np.nditer(a, flags=['c_index'])

while not it.finished:
    print("%d <%d>" % (it[0], it.index))
    it.iternext()

f_index:跟踪 F 顺序索引。示例如下:

import numpy as np

a = np.arange(24).reshape(2, 3, 4)
print(a)
it = np.nditer(a, flags=['f_index'])

while not it.finished:
    print("%d <%d>" % (it[0], it.index))
    it.iternext()

multi_index:跟踪每个维度的索引并返回一个元组。示例如下:

import numpy as np

a = np.arange(24).reshape(2, 3, 4)
print(a)
it = np.nditer(a, flags=['multi_index'])

while not it.finished:
    print("%d <%s>" % (it[0], it.multi_index))
    it.iternext()

转载请注明:文章转载自 www.mshxw.com
本文地址:https://www.mshxw.com/it/757010.html
我们一直用心在做
关于我们 文章归档 网站地图 联系我们

版权所有 (c)2021-2022 MSHXW.COM

ICP备案号:晋ICP备2021003244-6号