Numpy
1、Numpy是什么
NumPy(Numerical Python)是一个用于科学计算的Python库,它提供了高性能的多维数组对象以及用于处理这些数组的工具。NumPy提供了数学函数、线性代数运算、随机数生成等功能,是许多其他Python数据分析库的基础。NumPy的核心是ndarray(N-dimensional array),它是一个具有矢量化操作和广播功能的快速且灵活的数据容器
2、数据类型对象dtype
数据类型对象描述了对于的ndarray数组的信息,包括:① 数据类型 ② 数据大小 ③ 字节序(大端或小端) ④ 在结构化类型的情况下,字段的名称、每个字段的数据类型、每个字段占用的内存块部分 ⑤ 如果数据类型是子序列,它的形状和数据类型
dtype实例的构造:numpy.dtype(object,align,copy)
参数 | 描述 |
---|---|
object | 数据类型的字符串表示或 Python 类型 如果是字符串表示,它应该是 NumPy 所支持的数据类型之一,如 ‘int’、‘float’、‘complex’、‘bool’ 等 如果是 Python 类型,它应该是 Python 内置类型或 NumPy 支持的类型,如 int、float、complex、bool 等 默认值为 None,表示未指定数据类型 |
align | 布尔值,表示数据类型是否需要对齐存放,类似于C++中类的属性的存放 默认为 False,如果设为 True,则数据类型的大小将会按照平台的内存对齐规则进行对齐 |
copy | 布尔值,默认为 False,如果为True,则会创建一个独立的数据类型对象,而不是共享一个已存在的对象 |
import numpy as np
d1 = np.dtype(np.int) # 可以用传入np.类型,或者'类型'
d2 = np.dtype('int', copy=False)# copy为False,则创建时会检测是否已有int数据类型实例的存在,有的话则进行引用
print(d1 is d2)
d3 = np.dtype('int', copy=True)# copy为True,则不管是否已存在int数据类型实例,会创建一个新的int数据类型实例
print(d1 is d3)
#运行结果
True
False
np数据类型 | 字符串描述 | 描述 |
---|---|---|
np.bool_ | ‘b’ 或者 ‘bool’ | 存储一个字节的布尔值 |
np.int_ | / | 默认整数,相当于C的 long ,通常为 int32 或 int64 |
np.intc | / | 相当于C的int,通常为 int32 或 int64 |
np.intp | / | 用于索引的整数,相当于C的size_t,通常为 int32 或 int64 |
np.int8 | ‘i1’ 或者 ‘int8’ | 8位整数(-128~127) |
np.int16 | ‘i2’ 或者 ‘int16’ | 16位整数 |
np.int32 | ‘i4’ 或者 ’int32‘ | 32位整数 |
np.int64 | ‘i8’ 或者 ‘int64’ | 64位整数 |
np.uint8 | ‘u1’ 或者 ‘uint8’ | 8位无符号整数(0~255) |
np.uint16 | ‘u2’ 或者 ‘uint16’ | 16位无符号整数 |
np.uint32 | ‘u4’ 或者 ‘uint32’ | 32位无符号整数 |
np.unit64 | ‘u8’ 或者 ‘uint64’ | 64位无符号整数 |
np.float_ | ‘f8’ 或者 ‘float64’ | float64的简写 |
np.float16 | ‘f2’ 或者 ‘float16’ | 半精度浮点数,1位符号位,5位指数,10位尾数 |
np.float32 | ‘f4’ 或者 ‘float32’ | 单精度浮点数,1位符号位,8位指数,23位尾数 |
np.float64 | ‘f8’ 或者 ‘float64’ | 双精度浮点数,1位符号位,11位指数,52位尾数 |
np.complex_ | ‘c16’ 或者 ‘complex128’ | complex128的简写 |
np.complex64 | ‘c8’ 或者 ‘complex64’ | 32位浮点数的实部和32位浮点数的虚部 |
np.complex128 | ‘c16’ 或者 ‘complex128’ | 64位浮点数的实部和64位浮点数的虚部 |
(np.str_,长度) | (‘str’,长度) | 字符串,支持 Unicode 字符( 例如中文 ) |
(np.string_,长度) | ‘S长度’ | 字符串,不支持 Unicode 字符 |
(np.unicode_,长度) | (‘unicode’,长度) 或者 ‘U长度’ | 字符串,支持 Unicode 字符( 例如中文 ) |
字符代码 | 描述 |
---|---|
b | 布尔值 |
i | 符号整数 |
u | 无符号整数 |
f | 浮点 |
c | 复数浮点 |
m | 时间间隔 |
M | 日期时间 |
O | Python对象 |
S | 字符串 |
U | unicode |
V | 原始数据Void |
字节序 | 描述 |
---|---|
< | 小端(最小有效字节存储在低地址,有利于机器的处理) |
> | 大端(最大有效字节存储在低地址) |
import numpy as np
# int8、int16、int32、int64可以用i1、i2、i4、i8代替,其实就是8bit=1Byte的换算,其他同理
d1 = np.dtype('i4')
print(d1) # 输出:int32
d2 = np.dtype('u8')
print(d2) # 输出:unit64
d3 = np.dtype('>f2') # 采用大端存储
print(d3) # 输出:>f2
d4 = np.dtype(('str', 20))
print(d4) # 输出:<U20 ---变成unicode类型
print('-' * 30)
# 结构化数据类型,传入一个数组,由(键,类型)的元组组成
d5 = np.dtype([('age', 'i1'),
('name', np.str_, 10), # str支持中文
('address', ('str', 10)), # 字符串类型和长度可以写成元组的形式,也可以不要
('hobby', np.string_, 10), # string_不支持中文
('gender', 'U10')]) # unicode支持中文
arr = np.array([(10, "Niki", '杭州', 'basketball', '男'), (20, "Pyy", '苏州', 'football', '女')], dtype=d5)
print(arr['age'], arr['name'])
print(arr)
#运行结果
int32
uint64
>f2
<U20
------------------------------
[10 20] ['Niki' 'Pyy']
[(10, 'Niki', '杭州', b'basketball', '男')
(20, 'Pyy', '苏州', b'football', '女')]
3、Numpy 的数组对象 ndarray
ndarray是一个多维数组对象,由两部分组成:数据+描述这些数据的元数据(维度、类型…),不同于List的是,ndarray要求所有元素的类型相同,因为这样可以便于计算
属性 | 描述 |
---|---|
ndim | ndarray的秩,轴的数量或维度 对于一个3行2列的数组来说,其秩为3(取大) |
shape | 返回一个元组,表ndarray对象的形状 (几行几列) |
size | 数组中元素的个数 |
dtype | 数组中元素的数据类型 |
itemsize | 数组中元素的大小,以字节为单位 |
flags | 描述数组内存布局和其他属性的标志属性 |
import numpy as np
x = np.array([[1, 2, 3], [4, 5, 6]])
print(x.flags)
#运行结果
C_CONTIGUOUS : True
F_CONTIGUOUS : False
OWNDATA : True
WRITEABLE : True
ALIGNED : True
WRITEBACKIFCOPY : False
UPDATEIFCOPY : False
flags的属性 | 描述 |
---|---|
C_CONTIGUOUS (C) | 数组是否按照 C 风格的存储顺序(按行主序)进行存储,即相邻元素在内存中是连续存储的。对于二维数组,它按行存储 |
F_CONTIGUOUS (F) | 数组是否按照 Fortran 风格的存储顺序(按列主序)进行存储,即相邻元素在内存中是连续存储的。对于二维数组,它按列存储 |
OWNDATA (O) | 数组是否拥有自己的数据(即数据不是从其他对象借用的) 如果 O 是 True,则数组拥有自己的数据 如果 O 是 False,则数组共享数据(即数据是从其他对象借用的) |
WRITEABLE (W) | 数据区域是否可写入,如果值为flase表示该数组只读 |
ALIGNED (A) | 数组的数据是否是按照内存对齐规则进行存储的 |
WRITEBACKIFCOPY | 这个数组是另一数组的副本。当这个数组释放时,源数组会由这个数组中的元素更新 |
UPDATEIFCOPY (U) | 已弃用,用WRITEBACKIFCOPY代替 |
4、数组的创建方式
①:常规 —— array方法
numpy.array(object, dtype = None, copy = True, order = None, subok = False, ndmin = 0)
参数 | 描述 |
---|---|
object | 创建数组的对象,可以是 Python 序列(如列表、元组)、数组、或者其他实现了数组接口的对象 |
dtype | 所创建数组的数据类型,如果未指定则根据输入数据的类型来推断,常见的数据类型包括整数(如 numpy.int32)、浮点数(如 numpy.float64)等 |
copy | 指定是否复制输入数据,默认为 True,表示复制输入数据。如果为 False,数组将尽量在不复制数据的情况下使用输入对象的数据 |
order | 指定数组在内存中的存储顺序。有两种可能的选项 C:按行主序,行在内存中连续存储 F:按列主序,列在内存中连续存储 |
subok | 指定是否允许子类化数组,默认为 False,表示返回的数组不会是输入数组的子类,如果设置为 True,则返回的数组可以是输入数组的子类 |
ndmin | 指定返回数组的最小维度。默认值为 0,表示返回的数组可以是任意维度,如果指定了 ndmin,则返回的数组将至少具有指定的最小维度。例如,如果 ndmin=2,而输入的对象是一维的,则返回的数组将至少是二维的 |
import numpy as np
a = np.array([1, 2, 3], dtype=complex, ndmin=2)
print(a)
# 输出
# [[1.+0.j 2.+0.j 3.+0.j]]
②:其他方法
方法 | 描述 |
---|---|
np.zeros(shape) | 创建一个shape形状的全0数组,shape的类型为元组或整数(下同) |
np.zeros_like(a) | 创建一个跟a形状一样的全0数组 |
np.ones(shape) | 创建一个shape形状的全1数组 |
np.ones_like(a) | 创建一个跟a形状一样的全1数组 |
np.full(shape,value) | 创建一个shape形状的全value数组 |
np.full_like(a,value) | 创建一个跟a形状一样的全value数组 |
np.eye(n) | 创建一个 n x n 的单位矩阵 |
np.eye_like(a) | 创建跟a形状一样的单位矩阵 |
np.empty(shape) | 创建一个指定形状的未初始化数组 |
np.empty_like(a) | 创建一个跟a形状一样的未初始化数组 |
np.concatenate((a,b)) | 将多个数组合并成一个新的数组 如果连接的多个数组都是一维数组,可以任意连接 如果连接的多个数组是多维数组,形状必须一致 |
np.linspace(start,stop,num,endpoint=True,retstep) | 从start到stop等距填充num个数,endpoint是指要不要包含stop retstep默认为False,如果为True,则会顺便返回一个步长 |
np.logspace(start,stop,num,endpoint=True,base) | 从base ^ start到base ^ stop等距填充num个数,endpoint是指要不要包含base ^ stop base默认为10 |
np.arange([start] , stop , [step]) | 如果没有指定start和step,则为[0,1,2,…,stop-1] 如果有指定start和step,则为[start,…跨步step…,stop) |
np.random.randn(*dn) | 生成*dn形状的随机数数组 例如 np.random.randn(2,3) 或 np.random.randn(4,3,2) |
np.random.randint(low,high,shape) | 创建一个shape形状的元素值为low~high-1间随机数的数组 |
np.asarray(list) | 将list类型的数组转换成ndarray类型的数组 |
np.frombuffer(buffer,offset,count) | 从缓冲区(一块内存区域)的offset位置读取count的数据 offset默认为0,表示从头开始读取 count默认为-1,表示读取全部数据 |
np.fromiter(it,count) | 传入一个迭代器以构建一个ndarray对象,然后返回一个一维数组 count默认为-1,表示读取全部数据 |
import numpy as np
print('-' * 10, 'frombuffer:', '-' * 10)
buffer = b'hello world!' # 定义一个缓冲区对象 注意要写b表示这是一个bytes类型的数据
arr1 = np.frombuffer(buffer, dtype='S1')
arr2 = np.frombuffer(buffer, dtype='S2') # 如果要两个两个地读的话,要保证buffer的字符数能够整除2,其他同理
print(arr1)
print(arr2)
print('-' * 10, 'fromiter:', '-' * 10)
list = range(5)
it = iter(list)
x = np.fromiter(it, dtype=float)
print(x)
print('-' * 10, 'logspace:', '-' * 10)
arr2 = np.logspace(1, 2, num=10)
print(arr2)
#输出结果
---------- frombuffer: ----------
[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!']
---------- fromiter: ----------
[0. 1. 2. 3. 4.]
---------- logspace: ----------
[ 10. 12.91549665 16.68100537 21.5443469 27.82559402
35.93813664 46.41588834 59.94842503 77.42636827 100. ]
5、数组计算
①:广播:以复制的形式对自身进行扩展
②:两个形状不同的数组进行运算时,需要以广播后的形式(两者广播成相同的形状)进行运算
③:运算中的广播规则:①:后缘维度相同,例如(4,3,2)和(3,2)有共同的后缘维度,也就是后缀(3,2)②:在前面的基础上维度为1相当于斗地主的那种癞子,例如(4,3,2)和(1,2),1可以先扩展为3,使得两者有相同的回追(3,2);再例如(4,3,1)和(1,2)广播后有相同的后缀(3,2),于是可以进行运算
④:不符合运算过程的广播规则有例如:(4,4,4)、(2,2),(4,4)和(2,2)不一样,即使看着呈倍数关系,但是不行;(4,4,4)、(3,4,4),这里需要补充的是:后缘维度的长度要选定两者中的最小者,所以这里虽然两者都有(4,4),但是后缘维度要看3位,显然(4,4,4)、(3,4,4)不一样所以不行
import numpy as np
a = np.arange(start=1, stop=9).reshape((4, 2))
b = np.arange(start=1, stop=7).reshape((3, 1, 2))
# a的形状是(4,2) b的形状是(3,1,2)
# [[1 2] [[[1 2]]
# [3 4] [[3 4]]
# [5 6] [[5 6]]]
# [7 8]]
# 运算前的广播
# a进行广播(扩展)
# (4,2) => (1,4,2) => (3,4,2)
# [[1 2] [[[1 2] [[[1 2] [3 4] [5 6] [7 8]]
# [3 4] [3 4] [[1 2] [3 4] [5 6] [7 8]]
# [5 6] [5 6] [[1 2] [3 4] [5 6] [7 8]]]
# [7 8]] [7 8]]]
# b进行广播(扩展)
# (3,1,2) => (3,4,2)
# [[[1 2]] [[[1 2] [1 2] [1 2] [1 2]]
# [[3 4]] [[3 4] [3 4] [3 4] [3 4]]
# [[5 6]]] [[5 6] [5 6] [5 6] [5 6]]]]
# 于是可以运算得到结果
# [[[ 2 4] [ 4 6] [ 6 8] [ 8 10]]
# [[ 4 6] [ 6 8] [ 8 10] [10 12]]
# [[ 6 8] [ 8 10] [10 12] [12 14]]]
print(a + b)
类型 | 说明 |
---|---|
a+1、a-1 a*1、a÷1 | 数组a的所有元素都加/减/乘/除1 |
a+b、a-b a*b、a÷b (a b的形状相同) | a和b对应位置的元素相加/减/乘/除 (这里的乘注意不要跟矩阵乘法混淆) |
a+b、a-b a*b、a÷b (a b形状不同 但符合广播规则) | 看例子 |
例1:
import numpy as np
a = np.random.randint(1, 5, (2,))
b = np.random.randint(1, 5, (3,2))
print('a数组:\n', a)
print('b数组:\n', b)
print('相加:\n', a + b)
# 运行结果
a数组:
[3 1] # 计算时,a相当于变成 [[3,1]
b数组: # [3,1]
[[3 2] # [3,1]]
[2 4]
[2 3]]
相加:
[[6 3]
[5 5]
[5 4]]
例2:
import numpy as np
a = np.random.randint(1, 5, (2,))
b = np.random.randint(1, 5, (4,1))
print('a数组:\n', a)
print('b数组:\n', b)
print('相加:\n', a + b)
# 运行结果
a数组: # 计算时,a相当于变成 [[4,1]
[4 1] # [4,1]
b数组: # [4,1] # b在计算的时候相当于变成了
[[4] # [4,1]] # [[4,4]
[2] # [2,2]
[3] # [3.3]
[2]] # [2,2]]
相加:
[[8 5]
[6 3]
[7 4]
[6 3]]
例3:
import numpy as np
a = np.random.randint(1, 5, (3,2,2))
b = np.random.randint(1, 5, (2,2))
print('a数组:\n', a)
print('b数组:\n', b)
print('相加:\n', a + b)
#运行结果
a数组:
[[[3 1]
[1 4]]
[[2 3]
[4 2]]
[[4 2]
[1 2]]]
b数组: # b在计算的时候相当于变成了[[[2,2]
[[2 2] # [3,2]]
[3 2]] # [[2,2]
相加: # [3,2]]
[[[5 3] # [[2,2]
[4 6]] # [3,2]]]
[[4 5]
[7 4]]
[[6 4]
[4 4]]]
例4:
import numpy as np
a = np.random.randint(1, 5, (2,1,2))
b = np.random.randint(1, 5, (2,2))
print('a数组:\n', a)
print('b数组:\n', b)
print('相加:\n', a + b)
#运行结果
a数组: # a在计算的时候相当于变成了[[[2 4]
[[[2 4]] # [2 4]]
# [[1 3]
[[1 3]]] # [1 3]]]
b数组: # b在计算的时候相当于变成了[[[1 1]
[[1 1] # [2 4]]
[2 4]] # [1 1]
相加: # [2 4]]]
[[[3 5]
[4 8]]
[[2 4]
[3 7]]]
6、数组的变换
说明:下面描述中带 [原] 说明进行操作之后不改变原数组,而是返回一个进行操作得到的新数组,带 [改] 则说明会改变原数组
方法 | 描述 |
---|---|
arr.reshape(shape) | [原] 返回一个shape形状的数组,原数组不变 |
arr.resize(shape) | [改] 将原数组的形状改为shape |
arr.swapaxes(a,b) | [原] 将原n维数组的两个轴进行调换之后返回 例如对一个而数组进行swapaxes(0,1)相当于转置 |
arr.flatten(order) | [原] 将原数组折叠成一维数组后返回 order的值: 'C’按行 'F’按列 'A’按原顺序 'K’按在内存中出现的顺序 |
arr.flat[index] | [原] 将原数组折叠成一维数组后返回index下标的元素 |
arr.astype(元素数据类型) | [原] 将原数组中元素的类型进行转变后返回 |
arr.tolist() | [原] 将ndarray数组转变为list后返回 |
arr.transpose() 或者 arr.T | [原] 进行矩阵转置后返回 |
numpy.ravel(arr,order) | 将原数组折叠成一维数组后返回,功能通同flatten |
numpy.rollaxis(arr,axis,start) | 将arr的下标为axis的轴与第start个轴交换 axis从0开始,start从1开始 对于shape为(3,4,2)的数组,4的axis为1,start为2 |
import numpy as np
arr = np.random.randint(0, 10, (3, 4, 5))
print("原始数组的形状:", arr.shape)
# 3 4 5
# axis 0 1 2
# start 1 2 3
#将3和4对换,3的axis为0,4的start为2
result = np.rollaxis(arr, axis=0, start=2)
print("滚动轴后的数组形状:", result.shape)
#运行结果
原始数组的形状: (3, 4, 5)
滚动轴后的数组形状: (4, 3, 5)
7、数组维度的缩放
方法 | 描述 |
---|---|
np.broadcast(arr1,arr2,…) | 返回一个广播对象(arr1、arr2…要符合广播规则) |
import numpy as np
x = np.array([[1], [2], [3]]) # shape是(3,1),与y广播 =》(3,3)
y = np.array([4, 5, 6]) # shape是(3,),与x广播 =》(1,3)=》(3,3)
# x广播后 y广播后
# [[1,1,1], [[4,5,6],
# [2,2,2], [4,5,6],
# [3,3,3]] [4,5,6]]
b = np.broadcast(x, y) # x、y的广播对象,包含了广播后的x、广播后的y
print(b.shape) # 显然是(3,3)
print('-' * 30)
r, c = b.iters # 广播对象拥有iters属性,即广播后的x的迭代器、广播后的额y的迭代器
print(r.__next__(), c.__next__()) # 广播后的x的第一个元素是1,广播后的y的第一个元素是4
print(r.__next__(), c.__next__()) # 广播后的x的第二个元素是1,广播后的y的第二个元素是5
print('-' * 30)
b = np.broadcast(x, y) # 重新获取一个广播对象,因为上面的广播对象的迭代器发生移位了,重置一下
c = np.empty(b.shape) # 用于接收广播对象的两个数组相加的结果
c.flat = [u + v for (u, v) in b]
print(c)
print('-' * 30)
print(x + y)#当然也可以直接相加
(3, 3)
------------------------------
1 4
1 5
------------------------------
[[5. 6. 7.]
[6. 7. 8.]
[7. 8. 9.]]
------------------------------
[[5 6 7]
[6 7 8]
[7 8 9]]
方法 | 描述 |
---|---|
np.broadcast_to(arr,newshape) | 将arr广播成newshape的形状 |
np.expand_dims(arr,axis) | 插入新的轴 axis从0开始,0扩展的是最外层 |
np.squeeze(arr,axis) | 删除轴 |
import numpy as np
x = np.array([[1, 2], [3, 4]]) # (2,2)
print(x.shape)
y1 = np.expand_dims(x, 0)
print(y1.shape)
y2 = np.expand_dims(x, 1)
print(y2.shape)
z = np.squeeze(y2, 1)
print(z.shape)
#运行结构
(2, 2)
(1, 2, 2)
(2, 1, 2)
(2, 2)
8、数组的索引和切片
①:普通索引和切片
类别 | 用法 |
---|---|
索引 | 一维:数组名[下标] 二维:数组名[下标,下标] |
切片 | 一维:数组名[起始下标:结尾下标:步长] 二维:数组名[起始下标:结尾下标:步长,起始下标:结尾下标:步长] ( 结果不包含数组[结尾下标],步长默认为1) |
Tip:对于一维数组,arr[:]=arr[…]=整行
对于二维数组,arr[:,[1,2]]=arr[…,[1,2]]=所有行的一二列
import numpy as np
arr = np.random.randint(1, 10, (3,3))
print(arr)
print('-'*30)
print(arr[1][:])
print('-'*30)
print(arr[1][...])
print('-'*30)
print(arr[:,[0,2]])
#运行结果
[[9 4 9]
[6 9 9]
[6 4 1]]
------------------------------
[6 9 9]
------------------------------
[6 9 9]
------------------------------
[[9 9]
[6 9]
[6 1]]
②:迭代器nditer(order=‘K’,op_flags=None,flags=None)
order参数值 | 描述 |
---|---|
K | 按存储方式(按行 / 按列)进行遍历 |
C | 按行遍历 |
F | 按列遍历 |
op_flags参数值 | 描述 |
---|---|
readonly | 只读 |
radwrite | 读写 |
writeonly | 只写 |
flags参数值 | 描述 |
---|---|
c_index | 按行遍历 |
f_index | 按列遍历 |
milti-index | 会给迭代器天界一个multi-index属性,该属性是一个元组,表示当前元素的索引 |
external_loop | 返回的是一维数组,而不是数 |
例1:
import numpy as np
a = np.array([[0, 5, 10, 15], [20, 25, 30, 35], [40, 45, 50, 55]])
print('原始数组是:')
print(a)
print('a的C_CONTIGUOUS:', a.flags.c_contiguous)
print('a的F_CONTIGUOUS:', a.flags.f_contiguous)
print('迭代遍历a:')
for x in np.nditer(a):
print(x, end=' ')
print('')
b = a.T
print('原始数组的转置是:')
print(b)
print('b的C_CONTIGUOUS:', b.flags.c_contiguous)
print('b的F_CONTIGUOUS:', b.flags.f_contiguous)
print('迭代遍历b:')
for x in np.nditer(b):
print(x, end=' ')
print('')
c = a.copy(order='F')
print('数组c:')
print(c)
print('c的C_CONTIGUOUS:', c.flags.c_contiguous)
print('c的F_CONTIGUOUS:', c.flags.f_contiguous)
print('迭代遍历c:')
for x in np.nditer(c):
print(x, end=' ')
# 强制iter的遍历顺序
for x in np.nditer(c, order='C'):
print(x, end=' ')
print('')
# op_flags默认只读,可以设置为读写/只写模式 在只读情况下进行修改会报错
for x in np.nditer(c, op_flags=['readwrite']):
x *= 2
print(c)
原始数组是:
[[ 0 5 10 15]
[20 25 30 35]
[40 45 50 55]]
a的C_CONTIGUOUS: True #a是按行优先存储
a的F_CONTIGUOUS: False
迭代遍历a:#迭代器按行输出
0 5 10 15 20 25 30 35 40 45 50 55
原始数组的转置是:
[[ 0 20 40]
[ 5 25 45]
[10 30 50]
[15 35 55]]
b的C_CONTIGUOUS: False
b的F_CONTIGUOUS: True #b是a的转置,转置后变成按列有限存储
迭代遍历b: #迭代器按列输出
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]]
c的C_CONTIGUOUS: False
c的F_CONTIGUOUS: True #将a的存储方式变换一下
迭代遍历c:#按列输出
0 20 40 5 25 45 10 30 50 15 35 55
[[ 0 10 20 30]
[ 40 50 60 70]
[ 80 90 100 110]]
例2:
import numpy as np
# 创建一个二维数组
arr = np.array([[1, 2, 3],
[4, 5, 6],
[7, 8, 9]])
it1 = np.nditer(arr, flags=['multi_index'])
for x in it1:
print('当前的元素是:', x, ',其索引是:', it1.multi_index)
it2 = np.nditer(arr, flags=['external_loop'], order='F')
for x in it2:
print("当前行数据为:", x)
#运行结果
当前的元素是: 1 ,其索引是: (0, 0)
当前的元素是: 2 ,其索引是: (0, 1)
当前的元素是: 3 ,其索引是: (0, 2)
当前的元素是: 4 ,其索引是: (1, 0)
当前的元素是: 5 ,其索引是: (1, 1)
当前的元素是: 6 ,其索引是: (1, 2)
当前的元素是: 7 ,其索引是: (2, 0)
当前的元素是: 8 ,其索引是: (2, 1)
当前的元素是: 9 ,其索引是: (2, 2)
当前行数据为: [1 4 7]
当前行数据为: [2 5 8]
当前行数据为: [3 6 9]
例3:广播迭代
import numpy as np
a = np.arange(10, 70, 5).reshape(3, 4)
print('数组a:\n', a)
b = np.array([1, 2, 3, 4], dtype=int)
print('数组b:\n', b)
for x, y in np.nditer([a, b]):
if y != 4:
print('%d:%d' % (y, x), end='\t')
else:
print('%d:%d' % (y, x))
#运行结果
数组a:
[[10 15 20 25]
[30 35 40 45]
[50 55 60 65]]
数组b:
[1 2 3 4]
1:10 2:15 3:20 4:25
1:30 2:35 3:40 4:45
1:50 2:55 3:60 4:65
④:布尔索引
import numpy as np
arr = np.array([[3, 8, 5], [5, 7, 2], [1, 6, 3]])
print(arr)
print('-' * 30)
arr[arr <= 5] = 0
arr[(arr > 5) & (arr % 2 == 0)] = 1
print(arr)
print('-' * 30)
arr2 = np.array([np.nan, 1, 2, np.nan, 3, 4, 5])
print(arr2[~np.isnan(arr2)]) # 用~来过滤掉NaN
print('-' * 30)
arr3 = np.array([1, 2 + 6j, 5, 3.5 + 7j])
print(arr3[np.iscomplex(arr3)])
#运行结果
[[3 8 5]
[5 7 2]
[1 6 3]]
------------------------------
[[0 1 0]
[0 7 0]
[0 1 0]]
------------------------------
[1. 2. 3. 4. 5.]
------------------------------
[2. +6.j 3.5+7.j]
⑤:where(condiction,x,y)方法:
参数 | 说明 |
---|---|
condition | 条件数组,可以是一个布尔数组,也可以是可以转换为布尔数组的表达式 |
x(可选) | 满足条件的位置将使用 x 中的值,当未提供时,将返回满足条件的位置的索引 |
y(可选) | 不满足条件的位置将使用 y 中的值,当未提供时,将返回满足条件的位置的索引 |
import numpy as np
arr = np.random.randint(2, 10, size=(4,4))
print(arr)
arr[1:, :] = np.where(arr[1:, :] <= 6, 0, 1)# 从第二行起,对数组的相应部分进行修改
print(arr)
[[3 7 2 5]
[3 9 2 9]
[8 6 3 4]
[6 3 8 9]]
[[3 7 2 5]
[0 1 0 1]
[1 0 0 0]
[0 0 1 1]]
⑥:按轴索引(二维数组的轴就是行和列)
二维数组arr | 说明 |
---|---|
arr[slice(row1,row2,step)] | 选取二维数组的row1到row2行(不包括row2),步长为step |
arr[slice(row1,row2,step1),slice(column1,column2,step2)] | 选取二维数组的row1到row2行(不包括row2),步长为step1 以及column1到column2列(不包括column2),步长为step2 行列所交叉的元素 |
arr[[row1,row2]] | 选取二维数组的row1、row2行 |
arr[:,[column1,column2]] | 选取二维数组的column1、column2列 |
arr[[row1,row2],[column1,column2]] | 选取二维数组的row1行column1列、row2行column2列这两个元素 |
import numpy as np
arr = np.random.randint(1, 10, (8, 8))
print(arr)
print('-' * 30)
print(arr[slice(1, 4), slice(2, 5)])
print('-' * 30)
print(arr[[1, 4, 5], [1, 3, 5]])
#运行结果
[[6 1 2 6 1 6 1 8]
[9 2 8 2 3 4 7 1]
[6 9 6 5 6 1 9 5]
[5 6 3 2 5 6 6 9]
[1 2 6 2 5 3 4 4]
[3 1 8 2 1 4 5 7]
[5 7 3 9 6 2 2 3]
[5 9 4 1 5 7 6 2]]
------------------------------
[[8 2 3]
[6 5 6]
[3 2 5]]
------------------------------
[2 2 4]
9、数组的连接
方法 | 描述 | 注意点 |
---|---|---|
np.concatenate((arr1,arr2…),axis) | 沿着指定轴连接(合并) | 其他轴的形状要相同,例如(4,2,3) 和 (4,3,3) 如果沿着axis=1进行连接,两者其他两条轴都是(4,2),于是可以连接 反之,沿着axis=0和axis=2就不能 |
np.stack | 沿着指定的轴堆叠数组 | 数组的形状要相同,例如(2,2)和(2,2) |
np.hstack | 相当于concatenate((x, y), axis=1) | 其他轴的形状要相同 |
np.vstack | 相当于concatenate((x, y), axis=0) | 其他轴的形状要相同 |
合并与堆叠的区别:合并是中括号结合,堆叠是添加一层中括号
合并:[1,2]与[3,4]合并 ==》[1,2,3,4]
堆叠:[1,2]与[3,4]堆叠 ==》[[1,2],[3,4]]
import numpy as np
x = np.arange(0, 4).reshape((2, 2))
print(x) # [[0,1],[2,3]]
print('-' * 30)
y = np.arange(4, 8).reshape((2, 2))
print(y) # [[4,5],[6,7]]
print('-' * 30)
# 两个数组的第一级元素(自身)进行合并
z1 = np.concatenate((x, y), axis=0)
print(z1)
print('-' * 30)
# 两个数组的第二级元素进行合并(每个数组的二级元素各有两个,要分别([0,1]、[2,3]分别,[4,5]、[6,7]分别)对应着([0,1]和[4,5]对应,[2,3]和[6,7]对应)进行合并)
z2 = np.concatenate((x, y), axis=1)
print(z2)
print('-' * 30)
# 两个数组的第一级元素(自身)堆叠起来
z3 = np.stack((x, y), axis=0)
print(z3)
print('-' * 30)
# 两个数组的第二级元素堆叠起来(每个数组的二级元素各有两个,要分别([0,1]、[2,3]分别,[4,5]、[6,7]分别)对应着([0,1]和[4,5]对应,[2,3]和[6,7]对应)堆叠起来)
z4 = np.stack((x, y), axis=1)
print(z4)
print('-' * 30)
# 水平堆叠 相当于concatenate((x, y), axis=1)
z5 = np.hstack((x, y))
print(z5)
print('-' * 30)
# 垂直堆叠 相当于concatenate((x, y), axis=0)
z6 = np.vstack((x, y))
print(z6)
#运行结果
[[0 1]
[2 3]]
------------------------------
[[4 5]
[6 7]]
------------------------------
[[0 1]
[2 3]
[4 5]
[6 7]]
------------------------------
[[0 1 4 5]
[2 3 6 7]]
------------------------------
[[[0 1]
[2 3]]
[[4 5]
[6 7]]]
------------------------------
[[[0 1]
[4 5]]
[[2 3]
[6 7]]]
------------------------------
[[0 1 4 5]
[2 3 6 7]]
------------------------------
[[0 1]
[2 3]
[4 5]
[6 7]]
10、数组的分割
方法 | 描述 |
---|---|
np.split(ary,indices_or_sections,axis) | 对ary数组进行分割 indices_or_sections为整数表示要划分为等长的数组 indices_or_sections为一维数组表示要在一维数组元素指定的位置划分 axis默认为0 |
np.hsplit | 相当于split(ary,indices_or_sections,1) |
np.vsplit | 相当于split(ary,indices_or_sections,0) |
import numpy as np
a = np.arange(9)
print(a)
print('-'*30)
b1 = np.split(a, 3)
print(b1)
print('-'*30)
b2 = np.split(a, [4, 7])
print(b2)
print('-'*30)
c = np.arange(16).reshape(4, 4)
print(c)
print('-'*30)
d1 = np.hsplit(c, 2)
print(d1)
print('-'*30)
d2 = np.vsplit(c, 2)
print(d2)
#运行结果
[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])]
------------------------------
[[ 0 1 2 3]
[ 4 5 6 7]
[ 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, 2, 3],
[4, 5, 6, 7]]), array([[ 8, 9, 10, 11],
[12, 13, 14, 15]])]
11、数组的插入和删除
方法 | 描述 |
---|---|
np.append(arr,value,axis) | 将值添加到数组指定轴的末尾 没有指定axis时,会返回一个一维数组 |
np.insert(arr,obj,value,axis) | 将值添加数组指定轴的指定位置 没有指定axis时,会返回一个一维数组 |
np.delete(arr,obj,axis) | 删除数组指定轴的指定位置 没有指定axis时,会返回一个一维数组 |
np.unique(arr,return_index,return_inverse,return_counts) | 返回去重后的数组 return_index=True返回的是去重后的数组以及这些元素在原数组中的下标 return_inverse=True返回的是去重后的数组以及原数组的元素在去重后的数组中的下标 return_counts=True返回的是去重后的数组以及去重后的数组元素在原数组中出现的次数 |
import numpy as np
# append
a = np.array([[1, 2, 3], [4, 5, 6]])
print(a)
print('-' * 30)
print(np.append(a, [7, 8, 9]))
print('-' * 30)
print(np.append(a, [[7, 8, 9]], 0))
print('-' * 30)
print(np.append(a, [[7, 8, 9], [10, 11, 12]], 1))
print('-' * 30)
# insert
b = np.array([[1, 2], [3, 4], [5, 6]])
print(b)
print('-' * 30)
print(np.insert(b, 3, [7, 8]))
print('-' * 30)
print(np.insert(b, 2, [7, 8], axis=0))
print('-' * 30)
print(np.insert(b, 1, [7, 8, 9], axis=1))
print('-' * 30)
# delete
print(np.delete(b, 1, axis=0))
print('-' * 30)
# unique
c = np.array([5, 2, 6, 2, 7, 5, 6, 8, 2, 9])
print(np.unique(c))
print('-' * 30)
print(np.unique(c, return_index=True)[0], np.unique(c, return_index=True)[1])
print(np.unique(c, return_inverse=True)[0], np.unique(c, return_inverse=True)[1])
print(np.unique(c, return_counts=True)[0], np.unique(c, return_counts=True)[1])
#运行结果
[[1 2 3]
[4 5 6]]
------------------------------
[1 2 3 4 5 6 7 8 9]
------------------------------
[[1 2 3]
[4 5 6]
[7 8 9]]
------------------------------
[[ 1 2 3 7 8 9]
[ 4 5 6 10 11 12]]
------------------------------
[[1 2]
[3 4]
[5 6]]
------------------------------
[1 2 3 7 8 4 5 6]
------------------------------
[[1 2]
[3 4]
[7 8]
[5 6]]
------------------------------
[[1 7 2]
[3 8 4]
[5 9 6]]
------------------------------
[[1 2]
[5 6]]
------------------------------
[2 5 6 7 8 9]
------------------------------
[2 5 6 7 8 9] [1 0 2 4 7 9]
[2 5 6 7 8 9] [1 0 2 0 3 1 2 4 0 5]
[2 5 6 7 8 9] [3 2 2 1 1 1]
12、位操作
方法 | 描述 |
---|---|
np.bitwise_and(a,b) | 对数组元素按位与操作 |
np.bitwise_or(a,b) | 对数组元素按位或操作 |
np.invert(a) / ~a | 按位取反(不是取相反数) |
np.left_shift(a) | 左移 |
np.right_shift(a) | 右移 |
补充:np.binary_repr(value,width)表示将value转成width位的二进制补码,最高位(最左边)为符号位,剩余width-1位是数值位
import numpy as np
a, b = 13, 17
print('13的二进制', np.binary_repr(a, width=8))
print('17的二进制', np.binary_repr(b, width=8))
print('按位与运算', np.binary_repr(np.bitwise_and(a, b), width=8))
print('按位或运算', np.binary_repr(np.bitwise_or(a, b), width=8))
print('17按位取反', np.binary_repr(np.invert(b), width=8))
print('17左移两位', np.binary_repr(np.left_shift(b, 2), width=8))
print('17右移三位', np.binary_repr(np.right_shift(b, 3), width=8))
#运行结果
13的二进制 00001101
17的二进制 00010001
按位与运算 00000001
按位或运算 00011101
17按位取反 11101110
17左移两位 01000100
17右移三位 00000010
13、字符串操作
方法 | 描述 |
---|---|
np.char.add(str1,str2) | 逐个字符串连接 两个数组需要有相同的形状或者能够广播成相同形状 |
np.char.multiply(str,count) | 多重连接 |
np.char.center(str,width,fillchar) | str的两边连接width个fillchar |
np.char.capitalize(str) | 第一个单词的首字母大写 |
np.char.title(str) | 每个单词的首字母大写 |
np.char.lower(str) | 转小写 |
np.char.upper(str) | 转大写 |
np.charsplit(str,sep) | 以sep分割str |
np.char.splitlines(str) | 以换行符分割str |
np.char.join(sep,str) | 将sep插入到str的每个字符中 |
np.char.replace(str,old,new,count) | 将str中count个old替换成new |
np.char.encode(str,encoding) | 编码成encoding,默认为utf-8 |
np.char.decode(str,encoding) | 解码 |
np.strip(str,chars) | 去除首位特定字符,默认为空格 |
以上的参数中的str,既可以是字符串数组,也可以是单纯的一个字符串
import numpy as np
str1, str2 = ['hello '], ['world']
print(np.char.add(str1, str2))
str3, str4 = ['my ', 'is '], ['name', 'HYH']
print(np.char.add(str3, str4))
str5, str6 = ['I Love ', 'I hate '], ['you'] # 符合广播规则
print(np.char.add(str5, str6))
str7, str8 = 'good ', 'morning' # 也可以不要写成数组的形式
print(np.char.add(str7, str8))
print('-' * 30)
print(np.char.multiply('o', 10))
print('-' * 30)
print(np.char.center('HYH', 10, '_'))
print('-' * 30)
print(np.char.capitalize(['hello world', 'my name is hyh']))
print('-' * 30)
print(np.char.title('hello world, my name is hyh'))
print('-' * 30)
print(np.char.lower('Hello World, My Mame Is Hyh'))
print('-' * 30)
print(np.char.upper('Hello World, My Mame Is Hyh'))
print('-' * 30)
print(np.char.split('hello,world,my,name,is,hyh', sep=','))
print('-' * 30)
print(np.char.splitlines('hello\nworld\nmy\nname\nis\nhyh'))
print('-' * 30)
print(np.char.join([':', "-"], ['hhmmss', 'yyyymmdd']))
print('-' * 30)
print(np.char.replace('hello world world world world', 'world', 'hyh', 2))
print('-' * 30)
str9 = 'hello'
str9_encode = np.char.encode(str9, 'cp500')
print(str9_encode)
str9_decode = np.char.decode(str9_encode, 'cp500')
print(str9_decode)
print('-' * 30)
print(np.char.strip('aaaaaaahello worldaaaaaa', 'a'))
#运行结果
['hello world']
['my name' 'is HYH']
['I Love you' 'I hate you']
good morning
------------------------------
oooooooooo
------------------------------
___HYH____
------------------------------
['Hello world' 'My name is hyh']
------------------------------
Hello World, My Name Is Hyh
------------------------------
hello world, my mame is hyh
------------------------------
HELLO WORLD, MY MAME IS HYH
------------------------------
['hello', 'world', 'my', 'name', 'is', 'hyh']
------------------------------
['hello', 'world', 'my', 'name', 'is', 'hyh']
------------------------------
['h:h:m:m:s:s' 'y-y-y-y-m-m-d-d']
------------------------------
hello hyh hyh world world
------------------------------
b'\x88\x85\x93\x93\x96'
hello
------------------------------
hello world
14、算术函数
方法 | 描述 |
---|---|
np.sin(弧度)、np.cos(弧度)、np.tan(弧度) | 三角函数 |
np.degrees(弧度) | 将弧度转为角度 |
np.arcsin(正弦值)、np.arccos(余弦值)、np.arctan(正切值) | 反三角函数 |
np.around(f,decimals) | 默认个位四舍五入 decimals为正数,即小数四舍五入,例如decimals=1表示保留一位小数 decimals为负数,即整数位四舍五入,例如decimals=-1表示十位四舍五入 Tip:正好是5的话是舍,比5高的才是入例如5.00001 |
np.floor(f) | 向下取整 |
np.ceil(f) | 向上取整 |
np.add(a,b)、np.substract(a,b) np.multiply(a,b)、np.divide(a,b) | 数组的加减乘除,同第五小节:数组的计算 要注意运算两者是否符合广播规则 |
np.reciprocal(f) | 取倒数,0的话取倒数会报错 |
np.power(x1,x2) | 计算x1的x2次方 |
np.mod(a,b) | a对b取模 |
np.real( c ) | 返回实部 |
np.imag( c ) | 返回虚部 |
np.conj( c ) | 返回通过改变虚部的符号而获得的共轭复数 |
np.angle(c,deg) | 返回负数参数的角度,deg=True,则返回的角度以角度制表示,否则以弧度制表示 |
import numpy as np
# 一圈其实是弧度:2*pi,只不过平时为了方便理解和使用,引入了角度360°与弧度2*pi对应起来
# 因此实际上传入sin的应该是一个弧度,所以角度要进行换算:角度*2*pi/360=弧度
print('{:.5f}'.format(np.sin(30 * np.pi / 180)))
print('{:.5f}'.format(np.cos(45 * np.pi / 180)))
print('{:.5f}'.format(np.tan(45 * np.pi / 180)))
print('-' * 30)
print('{:.5f}'.format(np.degrees(np.arcsin(0.5))))
print('{:.5f}'.format(np.degrees(np.arccos(0.5))))
print('{:.5f}'.format(np.degrees(np.arctan(1))))
print('-' * 30)
f1 = [1.0, 5.55, 125.001, 0.567, 25.325]
print(np.around(f1))
print(np.around(f1, decimals=1))
print(np.around(f1, decimals=-1))
print('-' * 30)
print(np.ceil([10.0, 10.1]))
print(np.floor([10.0, 10.1]))
print('-' * 30)
print(np.reciprocal([2, 1, 0.5]))
print('-' * 30)
print(np.power([2, 4, 6], 2))
print('-' * 30)
print(np.mod([10, 20, 30], [3, 5, 7]))
print('-' * 30)
arr = np.array([-5.6j, 0.2j, 11, 1 + 2j])
print(np.real(arr))
print(np.imag(arr))
print(np.conj(arr))
print(np.angle(arr, deg=True))
#运行结果
0.50000
0.70711
1.00000
------------------------------
30.00000
60.00000
45.00000
------------------------------
[ 1. 6. 125. 1. 25.]
[ 1. 5.6 125. 0.6 25.3]
[ 0. 10. 130. 0. 30.]
------------------------------
[10. 11.]
[10. 10.]
------------------------------
[0.5 1. 2. ]
------------------------------
[ 4 16 36]
------------------------------
[1 0 2]
------------------------------
[-0. 0. 11. 1.]
[-5.6 0.2 0. 2. ]
[-0.+5.6j 0.-0.2j 11.-0.j 1.-2.j ]
[-90. 90. 0. 63.43494882]
15、统计函数
方法 | 描述 |
---|---|
np.amin(arr,axis) | 沿指定的轴返回最小值 |
np.amax(arr,axis) | 沿指定的轴返回最大值 |
np.ptp(arr,axis) | 沿指定的轴返回最大值和最小值差 |
np.percentile(arr,q,axis) | 沿指定的轴返回该轴从小到大排序的序列中位于q位置的元素 |
np.median(arr,axis) | 沿指定的轴返回中位数 |
np.mean(arr,axis) | 沿指定轴返回算数平均值(元素之和 / 元素个数) |
np.average(arr,axis,weights,returned) | 沿指定轴返回加权平均数 weights没有指定的话则返回的是算数平均数 returned=True的话顺带返回权重的和 |
np.std(arr,axis) | 沿指定轴返回标准差 相当于sqrt(mean((x-x.mean())**2)) |
np.var(arr,axis) | 沿指定轴返回方差 相当于mean((x-x.mean())**2) |
Tip1:统计函数中,以amin为例,axis为0时,不是得出每一行的最小值,而是得出每一列的最小值,axis为1时,不是得出每一列的最小值,而是得出每一行的最小值。跟之前的不太一样,其他的统计函数同理
Tip2:统计函数中没有指定轴的话,将会对所有元素进行统计,以amax为例,即会返回数组所有元素最大的
import numpy as np
# 五行五列
b = np.random.randint(0, 10, (5, 5))
print(b)
print('-' * 30)
print(np.percentile(b, 50))
print('-' * 30)
print(np.percentile(b, 50, axis=0)) # 一列五个元素,四个间隔,每个间隔是25%,第一个元素0%,第二个元素是25%...,所以相当于选出每列的中位数
print('-' * 30)
print(np.percentile(b, 50, axis=1)) # 一行五个元素,四个间隔,每个间隔是25%,第一个元素0%,第二个元素是25%...,所以相当于选出每行的中位数
print('-' * 30)
# 六行六列
c = np.random.randint(0, 10, (6, 6))
print(c)
print('-' * 30)
# 一行五个间隔,每个间隔20%,于是先跳到第二个元素(40%)此时剩下的10%占第二个元素和第三个元素间间隔(20%)的一半,所以取第二个元素和第三个元素的一半
print(np.percentile(c, 50, axis=1))
print('-' * 30)
d = np.random.randint(0, 10, (3, 3))
print(d)
print('-' * 30)
print(np.average(d, axis=1))
print('-' * 30)
print(np.average(d, axis=1, weights=[3, 2, 1]))
print('-' * 30)
print(np.average(d, axis=1, weights=[3, 2, 1], returned=True))
#运行结果
[[0 3 3 7 6]
[0 7 8 2 5]
[9 2 8 9 3]
[7 6 9 3 8]
[9 4 8 6 2]]
------------------------------
6.0
------------------------------
[7. 4. 8. 6. 5.]
------------------------------
[3. 5. 8. 7. 6.]
------------------------------
[[9 6 4 6 0 7]
[5 8 8 6 5 4]
[7 3 0 7 2 0]
[9 6 0 6 2 1]
[6 9 0 9 9 0]
[9 5 6 1 3 9]]
------------------------------
[6. 5.5 2.5 4. 7.5 5.5]
------------------------------
[[3 5 4]
[7 7 6]
[8 4 1]]
------------------------------
[4. 6.66666667 4.33333333]
------------------------------
[3.83333333 6.83333333 5.5 ]
------------------------------
(array([3.83333333, 6.83333333, 5.5 ]), array([6., 6., 6.]))
16、排序函数
方法 | 描述 |
---|---|
np.sort(arr,axis,kind,order) | 升序排序,kind是排序算法,order是排序的字段 kind的值有快速排序quicksort、归并排序mergesort、堆排序heapsort等 |
np.argsort(arr,axis) | 返回排序后的元素在排序前序列中的下标 |
np.lexsort(keys,axis) | 按照多个键对数据进行排序,返回的也是排序后的元素在排序前序列中的下标 keys 是一个元组或者数组列表,其中包含了需要排序的键。每个键可以是一个数组 靠后的键优先排序,例如keys=(arr1,arr2)先按照键arr2进行排序完了再排到arr1 |
import numpy as np
dt = np.dtype([('name', 'S10'), ('age', int)])
a = np.array([[('Niki', 43), ("Pyy", 23), ("Zayn", 39), ("HYH", 37)]], dtype=dt)
print(a)
print('-' * 30)
print(np.sort(a, kind='mergesort', order='age'))
print('-' * 30)
b = np.random.randint(0, 100, (10,))
print(b)
print('-' * 30)
print(np.argsort(b))
print('-' * 30)
print(b[np.argsort(b)])
print('-' * 30)
name = ["Zayn", "Pyy", "Niki", "Yh"]
age = [21, 47, 21, 37]
ind = np.lexsort((name, age))
print([name[i] + ',' + str(age[i]) for i in ind])
#运行结果
[[(b'Niki', 43) (b'Pyy', 23) (b'Zayn', 39) (b'HYH', 37)]]
------------------------------
[[(b'Pyy', 23) (b'HYH', 37) (b'Zayn', 39) (b'Niki', 43)]]
------------------------------
[55 25 26 77 77 37 93 80 33 28]
------------------------------
[1 2 9 8 5 0 3 4 7 6]
------------------------------
[25 26 28 33 37 55 77 77 80 93]
------------------------------
['Niki,21', 'Zayn,21', 'Yh,37', 'Pyy,47']
17、搜索函数
方法 | 描述 |
---|---|
np.argmin(arr,axis) | 返回最小的元素在排序前序列的索引 |
np.argmax(arr,axis) | 返回最大的元素在排序前序列的索引 |
np.nonzero(arr,axis) | 返回非零元素的索引 |
np.where(condiction) | 返回满足条件的数组元素索引 |
np.extract(condiction,arr) | 返回满足条件的元素 |
import numpy as np
a = np.arange(9).reshape(3, 3)
print(a)
print('-' * 30)
print(np.where(a > 3))
print('-' * 30)
print(a[np.where(a > 3)])
print('-' * 30)
b = np.arange(9).reshape(3, 3)
print(b)
print('-' * 30)
condiction = np.mod(b, 2) == 0
print(np.extract(condiction, b))
#运行结果
[[0 1 2]
[3 4 5]
[6 7 8]]
------------------------------
(array([1, 1, 2, 2, 2], dtype=int64), array([1, 2, 0, 1, 2], dtype=int64))
------------------------------
[4 5 6 7 8]
------------------------------
[[0 1 2]
[3 4 5]
[6 7 8]]
------------------------------
[0 2 4 6 8]
18、复制
方式 | 描述 |
---|---|
arr1=arr2 | 引用的相同的数据对象 |
arr1=arr2.view() | 创建视图,引用的相同的数据缓冲区 也就是指向不同的内存区域,但是数据的来源指向同一块内存区域 |
arr1=arr2.copy() | 创建新的数据对象 |
import numpy as np
# 赋值 指向相同的内存区域
a1 = np.arange(6).reshape((2, 3))
print(a1)
a2 = a1
a2.shape = (3, 2)
print(a1)
print('-' * 30)
# 视图 指向不同的内存区域 但数据来自同一块内存区域
b1 = np.arange(6).reshape((2, 3))
print(b1)
b2 = b1.view()
b2[0][0] = 100
b2.shape = (3, 2)
print(b1)
print(b2)
print('-' * 30)
# 深复制
c1 = np.arange(6).reshape((2, 3))
print(c1)
c2 = c1.copy()
c2[0][0] = 100
c2.shape = (3, 2)
print(c1)
print(c2)
#运行结果
[[0 1 2]
[3 4 5]]
[[0 1]
[2 3]
[4 5]]
------------------------------
[[0 1 2]
[3 4 5]]
[[100 1 2]
[ 3 4 5]]
[[100 1]
[ 2 3]
[ 4 5]]
------------------------------
[[0 1 2]
[3 4 5]]
[[0 1 2]
[3 4 5]]
[[100 1]
[ 2 3]
[ 4 5]]
19、矩阵计算
方法 | 描述 |
---|---|
np.dot(arr1,arr2) np.vdot(arr1,arr2) np.inner(arr1,arr2) | 计算两个数组的点积 计算两个数组的向量内积 计算两个数组的内积 区别:看例子 |
np.matmul | 用于计算两个数组的矩阵乘积 |
np.linalg.det(arr) | 计算行列式 |
np.linalg.solve(A,B) | 计算线性方程的解 |
np.linalg.inv(arr) | 计算矩阵的逆矩阵 |
import numpy as np
arr1 = np.arange(1, 5).reshape((2, 2)) # [[1,2],[3,4]]
arr2 = np.arange(11, 15).reshape((2, 2)) # [[11,12],[13,14]]
# dot (计算二维数组的矩阵乘法时相当于matmul(arr1,arr2)或者arr1@arr2)
# [ 1*11+2*13 , 1*12+2*14 , 3*11+4*13 , 3*12+4*14 ]
print(np.dot(arr1, arr2))
print('-' * 30)
# vdot
# 1*11+2*12+3*13+4*14
print(np.vdot(arr1, arr2))
print('-' * 30)
# inner
# [1*11+2*12 , 1*13+2*14 , 3*11+4*12 , 3*13+4*14]
print(np.inner(arr1, arr2))
print('-' * 30)
arr3 = [[1, 2], [3, 4]]
print(np.round(np.linalg.det(arr3), 2))
print('-' * 30)
A = np.array([[2, 1], [1, 1]])
B = np.array([3, 2])
print(np.linalg.solve(A, B)) # 求解AX=B
print('-' * 30)
arr4 = np.array([[1, 2], [3, 4]])
print(np.linalg.inv(arr4))
#运行结果
[[37 40]
[85 92]]
------------------------------
130
------------------------------
[[35 41]
[81 95]]
------------------------------
-2.0
------------------------------
[1. 1.]
------------------------------
[[-2. 1. ]
[ 1.5 -0.5]]
20、IO操作
方法 | 描述 |
---|---|
np.save(file,ndarray) | 将ndarray对象保存到npy文件中 |
np.load(file) | 从npy文件中加载ndarray对象 |
np.save(file,ndarray) | 将ndarray对象保存到txt文件中 |
np.load(file) | 从txt文件中加载ndarray对象 |
import os
import numpy as np
arr = np.array([1, 2, 3, 4, 5])
if os.path.exists('./outfile.npy'):
arr = np.load('./outfile.npy')
print(arr)
else:
np.save('./outfile.npy', arr)
if os.path.exists('./outfile.txt'):
arr = np.loadtxt('./outfile.txt')
print(arr, type(arr))
else:
np.savetxt('./outfile.txt', arr)
#运行结果
[1 2 3 4 5]
[1. 2. 3. 4. 5.] <class 'numpy.ndarray'>
21、其他
字节交换:arr.byteswap(True)
import numpy as np
# 以1为例,内存中存储的是00 01(十六进制),大小端互换后变成01 00(十六进制)也就是256
arr = np.array([1, 256, 8755], dtype=np.int16)
print(arr)
arr.byteswap(True)
print(arr)
#运行结果
[ 1 256 8755]
[ 256 1 13090]
声明
本文参考了:
布客飞龙(简书) 的文章 TutorialsPoint NumPy 教程
感谢大牛们的分享和帮助!