Python的NumPy库(一)基础用法

NumPy库并不是Python的标准库,但其在机器学习、大数据等很多领域有非常广泛的应用,NumPy本身就有比较多的内容,全部的学习可能涉及许多的内容,但我们在这里仅学习常见的使用,这些内容对于我们日常使用NumPy是足够的。

NumPy简介

NumPy是Python中科学计算的基础包,它代表 “Numeric Python”。Numeric,即 NumPy 的前身,是由 Jim Hugunin 开发的。 也开发了另一个包 Numarray ,它拥有一些额外的功能。 2005年,Travis Oliphant 通过将 Numarray 的功能集成到 Numeric 包中来创建 NumPy 包。

NumPy的核心是多维数组(ndarray),以及用于数组快速操作的各种API,有包括数学、逻辑、形状操作、排序、选择、输入输出、离散傅立叶变换、基本线性代数,基本统计运算和随机模拟等等。

NumPy数组 和 原生Python Array(数组)之间有几个重要的区别:

  • NumPy 数组在创建时具有固定的大小,与Python的原生数组对象(可以动态增长)不同。更改ndarray的大小将创建一个新数组并删除原来的数组。
  • NumPy 数组中的元素都需要具有相同的数据类型,因此在内存中的大小相同。 例外情况:Python的原生数组里包含了NumPy的对象的时候,这种情况下就允许不同大小元素的数组。
  • NumPy 数组有助于对大量数据进行高级数学和其他类型的操作。通常,这些操作的执行效率更高,比使用Python原生数组的代码更少。
  • 越来越多的基于Python的科学和数学软件包使用NumPy数组; 虽然这些工具通常都支持Python的原生数组作为参数,但它们在处理之前会还是会将输入的数组转换为NumPy的数组,而且也通常输出为NumPy数组。换句话说,为了高效地使用当今科学/数学基于Python的工具(大部分的科学计算工具),你只知道如何使用Python的原生数组类型是不够的 - 还需要知道如何使用 NumPy 数组。

NumPy数组主要是用来解决数学问题,包括功能(矩阵计算)和性能两个方面,并且性能更为关键。

NumPy数组主要是用来解决数学问题的,所以需要学习者具备一定的数学知识,比如矩阵、线性代数等等,本文假定学习者已经掌握了这些数学基础知识。

NumPy多维数组定义

NumPy多维数组有多种定义方法,我们主要学习常见的几种。

对象构造方法

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

返回NumPy数组。

参数说明:

  • object:初始化的数组值,可以是Python数组,也可以是序列类型的对象,如果是一个嵌套的序列对象,就会生成一个多维数组
  • dtype: 数组元素的数据类型。
  • copy :对象是否被复制。
  • order :排序方式,C(按行)、F(按列)或A(任意,默认)。
  • subok: 默认情况下,返回的数组被强制为基类数组。 如果为true,则返回子类。
  • ndmin :指定返回数组的最小维数。

数组对象的属性

NumPy 数组的维数称为秩(rank),秩就是轴(axis)的数量,可以相像为坐标轴,一维数组就是一维坐标轴,二维数组就是二维坐标轴,依次类推。

axis=0,表示第1条轴,一般我们称之为横轴,实际是沿着横轴对每一列进行操作。

axis=1,表示第2条轴,一般我们称之为纵轴,实际是沿着纵轴对每一行进行操作。

属性说明
ndarray.ndim秩,即轴的数量或维度的数量
ndarray.shape数组的形状,就是各维度的元素数的列表,例如举证就是(n,m),维度数相同但形状并不一定相同,例如矩阵都是二位的,但(3,3)的矩阵和(4,3)的矩阵形状是不同的
ndarray.size数组元素的总个数,相当于 .shape 中 n*m 的值
ndarray.dtypendarray 对象的元素类型
ndarray.itemsizendarray 对象中每个元素的大小,以字节为单位
ndarray.flagsndarray 对象的内存信息
ndarray.realndarray元素的实部
ndarray.imagndarray 元素的虚部
ndarray.data包含实际数组元素的缓冲区,由于一般通过数组的索引获取元素,所以通常不需要使用这个属性。

注意:初学者很容易将维度和形状搞混淆,维度是坐标轴的概念,一维就是一条直线,二维就是十字交叉的坐标轴,三维就是立方体一样的三轴坐标。 形状是比维度之下的长度的描述,描述的是各维度的长度,如一维的形状就是描述一条线段的长度(5个元素长度就是5,100个元素长度就是100),二维的形状就是描述长方形的两条边的长度,长是横轴,宽是纵轴,用二元元组描述横轴和纵轴,三维的形状就是描述长方体的三条边的长度,长、宽、高的三元组。同样是二维数组,会因为形状不同而不同,如长宽是(3,2)的数组和长宽为(2,3)是完全不同的两个数组。

几个维度在numpy是通过嵌套几层中括号来表示的,形状是通过中括号里的元素个数来表示的(中括号里的每一个中括号也是一个元素)。

a = np.array([[1,2,3,4], [10,20+5j,30+1j,40+2j]])
print(a)
print(a.ndim) #2
print(a.shape) #(2, 4)
print(a.dtype) #int64
print(a.itemsize) #8
print(a.flags)
# C_CONTIGUOUS: True
# F_CONTIGUOUS: False
# OWNDATA: True
# WRITEABLE: True
# ALIGNED: True
# WRITEBACKIFCOPY: False
print(a.real)
#[[ 1.  2.  3.  4.]
# [10. 20. 30. 40.]]
print(a.imag)
#[[0. 0. 0. 0.]
# [0. 5. 1. 2.]]
print(a.data)
#<memory at 0x108540040>

基于序列类型创建数组

可以基于序列类型生成数组,元素的类型并不限定为数值型,最终元素的类型会被转换为dtype:

import numpy as npa = np.array([1,2,3,4])
print(a) #[1 2 3 4]b = np.array(['a','b','c', 'd'])
print(b) #['a' 'b' 'c' 'd']c = np.array(['abc', 'def'])
print(c) #['abc' 'def']

如果元素的类型不一致会ValueError的异常:

a = np.array([1,2,3,4, [1,2]])
print(a)
#ValueError: setting an array element with a sequence. 

但注意:python会根据输入的数据类型的兼容性,进行自我适应,调整最终的dtype对象:

import numpy as npa = np.array([1,2,3,4,2])
print(a) #[1 2 3 4 2]
print(a.dtype) #int64
a = np.array([1,2,3,4,2.0])
print(a) #[1. 2. 3. 4. 2.]
print(a.dtype) #float64
a = np.array([1,2,3,4,'ab'])
print(a.dtype) #<U21
print(a) #['1' '2' '3' '4' 'ab']

元素也可以支持字典:

s = np.array([{1:'1'}, {2:'2', 3:'3'}])
print(s) #[{1: '1'} {2: '2', 3: '3’}]
print(s.dtype) #object

元素也支持自定义对象

class MyClass:def __init__(self, a, b):self.a = aself.b = bdef __repr__(self):return f'(MyClass {self.a=}, {self.b=})'def foo(self):passc = np.array([MyClass(1, 2), MyClass('s', 'c')])
print(c) #[(MyClass self.a=1, self.b=2) (MyClass self.a='s', self.b='c')]
print(c.dtype) #object

字典和自定义类都被识别为object类型,所以它们也可以被放在一起:

c = np.array([MyClass(1, 2), MyClass('s', 'c'), MyClass2(), {2:'2', 3:'3'}])
print(c) #[(MyClass self.a=1, self.b=2) (MyClass self.a='s', self.b='c') <__main__.MyClass2 object at 0x1094ae050> {2: '2', 3: '3'}]
print(c.dtype) #object

如果要生成多维数组,需要列表对象是嵌套对象:

import numpy as npa = np.array([[1,2,3,4], [10,20,30,40]])
print(a) 
'''
[[ 1  2  3  4][10 20 30 40]]'''

如果直接使用元组作为元素,NumPy会把它识别为多维数组:

a = np.array([(1,2,3,4), (10,20,30,40)])
print(a)
‘’’
[[ 1  2  3  4][10 20 30 40]]
’‘’

也可以通过指定ndmin来指定最小维数

b = np.array(('a', 'b', 'c'), ndmin=2)
print(b)
#[['a' 'b' 'c']]

通过dtype指定数组元素的类型:

c = np.array((20,30,40,50), ndmin=2, dtype=complex)
print(c)
#[[20.+0.j 30.+0.j 40.+0.j 50.+0.j]]

dtype支持的数值类型

numpy 支持的数据类型比 Python 内置的类型要多很多,基本上可以和 C 语言的数据类型对应上,其中部分类型对应为 Python 内置的类型。下表列举了常用 NumPy 基本类型:

类型代码说明
bool_b布尔型数据类型(True 或者 False)
int_默认的整数类型(类似于 C 语言中的 long,int32 或 int64)
intc与 C 的 int 类型一样,一般是 int32 或 int 64
intp用于索引的整数类型(类似于 C 的 ssize_t,一般情况下仍然是 int32 或 int64)
int8、uint8i1、u1有符号位和无符号位的8bit整数,相当于一个字节
int16、uint16i2、u2有符号位和无符号位的16bit整数,2字节整数
int32、uint32i4、u4有符号位和无符号位的32bit整数,4字节整数
int64、uint64i8、u8有符号位和无符号位的64bit整数,8字节整数
float_float64 类型的简写
float16f2半精度浮点数,包括:1 个符号位,5 个指数位,10 个尾数位
float32f4单精度浮点数,包括:1 个符号位,8 个指数位,23 个尾数位
float64f8双精度浮点数,包括:1 个符号位,11 个指数位,52 个尾数位
complex_complex128 类型的简写,即 128 位复数
complex64c8复数,表示双 32 位浮点数(实数部分和虚数部分)
complex128c16复数,表示双 64 位浮点数(实数部分和虚数部分)
bytesSC格式的字符串
UnicodeUUnicode格式的字符串

数据类型对象(numpy.dtype 类的实例)用来描述与数组对应的内存区域是如何使用,它描述了数据的以下几个方面::

  • 数据的类型(整数,浮点数或者 Python 对象)
  • 数据的大小(例如, 整数使用多少个字节存储)
  • 数据的字节顺序(小端法或大端法),通过对数据类型预先设定 < 或 > 来决定的。 < 意味着小端法(最小值存储在最小的地址,即低位组放在最前面)。> 意味着大端法(最重要的字节存储在最小的地址,即高位组放在最前面)。
  • 在结构化类型的情况下,字段的名称、每个字段的数据类型和每个字段所取的内存块的部分
  • 如果数据类型是子数组,那么它的形状和数据类型是什么。
numpy.dtype(object, align, copy)

返回NumPy的数据类型

参数说明:

  • object - 要转换为的数据类型对象
  • align - 如果为 true,填充字段使其类似 C 的结构体。
  • copy - 复制 dtype 对象 ,如果为 false,则是对内置数据类型对象的引用
dt = np.dtype(np.int32)
print(dt)
#int32dt = np.dtype('i4')
print(dt)
#int32dt = np.dtype('<i4')
print(dt)
#int32

将数据类型应用于 ndarray 对象:

dt = np.dtype([('age',np.int8)])
a = np.array([(10,),(20,),(30,)], dtype = dt)
print(a)
#[(10,) (20,) (30,)]

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

STUDENT = np.dtype([('name','S20'), ('age', 'i1'), ('marks', 'f4')])
print(STUDENT)
#[('name', 'S20'), ('age', 'i1'), ('marks', '<f4')]
a = np.array([('John', 12, 91.5),('Rose', 13, 99)], dtype = STUDENT)
print(a)
#[(b'John', 12, 91.5) (b'Rose', 13, 99. )]
print(a.dtype)
#[('name', 'S20'), ('age', 'i1'), ('marks', '<f4')]

从上面的例子可以看出,dtype定义的结构并没有被识别为object,而是一种带描述的结构体。

软拷贝数组

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

numpy.asarray 类似 numpy.array,基于存在的对象a(必须是数组,或序列等)创建一个新的数组对象。

array()和asarray()方法都能将序列对象转换为NumPy数组,二者:

  • 当他们的参数是列表型数据(list)时,二者没有区别;
  • 当他们的参数是数组类型(array)时,np.array()会返回参数数组的一个副本(copy,两者值一样但指向不同的内存),np.asarray()会返回参数数组的一个视图(两者指向同一块内存).
  • np.array()的副本会新开辟一块内存,对于大数组来说,会存在大量的复制操作,速度更慢且需要耗费大量内存;
  • np.asarray()的视图相当于新增加了一个指向当前内存的引用,不存在复制操作,速度更快且节约内存。注意通过其中的一个引用修改数据,其他引用的数据也会跟着变,因为他们指向同一块内存区域。
a1 = np.asarray([[1, 2, 3], [4, 5, 6]])
print(f'{a1=}')
b1 = np.asarray(a1)
print(f'{b1=}')
b2 = np.array(a1)
print(f'{b2=}')
a1[1][1] = 10
print('-------')
print(f'{a1=}')
print(f'{b1=}')
print(f'{b2=}’)‘’'
a1=array([[1, 2, 3],[4, 5, 6]])
b1=array([[1, 2, 3],[4, 5, 6]])
b2=array([[1, 2, 3],[4, 5, 6]])
-------
a1=array([[ 1,  2,  3],[ 4, 10,  6]])
b1=array([[ 1,  2,  3],[ 4, 10,  6]])
b2=array([[1, 2, 3],[4, 5, 6]])
‘''

创建空数组

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

创建一个指定形状(shape)、数据类型(dtype)且未初始化的数组。

参数说明:

  • shape:数组的形状元组,例如矩阵表示为(n,m),就是n 行 m 列;
  • dtype:元素的类型,默认是浮点数;
  • order:数组在内存中的存储顺序,'C' 是C 的行数组,或者 'F'是 FORTRAN 的列数组。
x = np.empty((3,2), dtype=int)
print(x)
‘’'
[[   0 2043][   1    0][   0    0]]
‘''

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

创建0填充数组

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

创建指定维度的数组,数组元素以 0 来填充

参数说明:

  • shape:数组的形状;
  • dtype:元素的类型,默认是浮点数;
  • order:数组在内存中的存储顺序,'C' 是C 的行数组,或者 'F'是 FORTRAN 的列数组。
x = np.zeros((3,2), dtype=int)
print(x)
y = np.zeros((2,3), dtype=[('NAME', 'S20'), ('AGE', 'i2')])
print(y)‘’'
[[0 0][0 0][0 0]]
[[(b'', 0) (b'', 0) (b'', 0)][(b'', 0) (b'', 0) (b'', 0)]]
‘''

创建1填充数组

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

创建指定维度的形状,数组元素以 1 来填充,与0填充一样,只是换成用1来填充。

创建n填充数组

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

创建指定维度的形状,数组元素以 fill_value来填充,与0填充一样,只是换成用1来填充。

x = np.full((3,2), 'OK')
print(x)
’’’
[['OK' 'OK']['OK' 'OK']['OK' 'OK’]]
‘’‘

仿制0填充数组

numpy.zeros_like(a, dtype=None, order='K', subok=True, shape=None)

用于创建一个与给定数组具有相同形状的数组,数组元素以 0 来填充。

参数说明:

  • a:要仿制的数组
  • dtype:元素的类型,默认是浮点数;
  • order:数组在内存中的存储顺序,可选值为 'C'(按行优先)或 'F'(按列优先),默认为 'K'(保留输入数组的存储顺序);
  • subok:是否允许返回子类,如果为 True,则返回一个子类对象,否则返回一个与 a 数组具有相同数据类型和存储顺序的数组;
  • shape:创建的数组的形状,如果不指定,则默认为 a 数组的形状。
a = np.array([[1, 2, 3], [4, 5, 6], [7, 8, 9]])
za = np.zeros_like(a)
print(za)
‘’'
[[0 0 0][0 0 0][0 0 0]]
‘''

仿制1填充数组

numpy.ones_like(a, dtype=None, order='K', subok=True, shape=None)

创建一个与给定数组具有相同形状的数组,与仿制0填充数据一样,只是数组元素以 1 来填充。

仿制n填充数组

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

创建一个与给定数组具有相同形状的数组,与仿制0填充数据一样,只是数组元素以 fill_value 来填充。

从流创建数组

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

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

注意:buffer 是字符串的时候,Python3 默认 str 是 Unicode 类型,所以要转成 bytestring 在原 str 前加上 b。

参数说明:

  • buffer:任意流对象
  • dtype:数组的元素类型
  • count:读取的数据数量,默认为-1,读取所有数据。
  • offset:流的偏移量,默认为0
bs = b'This is a test case!'
a = np.frombuffer(bs, dtype='S2')
print(a)
#[b'Th' b'is' b' i' b's ' b'a ' b'te' b'st' b' c' b'as' b'e!']

从迭代器创建数组

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

可迭代对象中建立 ndarray 对象,返回一维数组。

参数说明:

  • iterable:待提供数据的迭代器
  • dtype:数组的元素类型
  • count:读取的数据数量,默认为-1,读取所有数据。
it = iter(range(5))
x = np.fromiter(it, dtype=int)
print(x) #[0 1 2 3 4]

创建范围数组

类似于Python的range:

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

参数说明:

  • start:起始值,创建的数组包含这个数(闭区间)
  • stop:终止值,创建的数组将不包含这个数(开区间)
  • step:步长,默认是1
  • dtype:数组的元素类型,如果没有提供,则会使用输入数据的类型。
import numpy as npx = np.arange(5)  
print (x) #[0  1  2  3  4]

构建等差数列数组

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

创建一个一维数组,数组的元素是一个等差数列。

参数说明:

  • start:起始值,创建的数组包含这个数(闭区间)
  • end:终止值,如果endpointtrue,该值包含于数列中
  • num:要生成的等步长的样本数量,默认为50
  • endpoint:该值为 true 时,数列中包含stop值,反之不包含,默认是True。
  • retstep:如果为 True 时,生成的数组中会显示间距,反之不显示。
  • dtype:数组的元素类型

numpy.linspace是numpy.arange的增强版本。

a = np.linspace(10, 15, num=6, dtype=float)
print(a) #[10. 11. 12. 13. 14. 15.]
a = np.linspace(10, 20, num=6, dtype=float)
print(a) #[10. 12. 14. 16. 18. 20.]
a = np.linspace(10, 20, num=6, endpoint=False, dtype=float)
print(a) #[10.         11.66666667 13.33333333 15.         16.66666667 18.33333333]
#10, 10+1+2/3, 10+(1+2/3)*2, 10+(1+2/3)*3, 10+(1+2/3)*4, 10+(1+2/3)*5, 10+(1+2/3)*6=20 
a = np.linspace(10, 19, num=6, endpoint=False, dtype=float)
print(a) #[10.  11.5 13.  14.5 16.  17.5]

如果endpoin=Fasle,实际是把num计算为num+1,然后取前面的num位。

构建等比数列数组

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

创建一个于等比数列数组。

参数说明:

  • start:起始值,创建的数组包含这个数(闭区间)
  • end:终止值,如果endpointtrue,该值包含于数列中
  • num:要生成的等步长的样本数量,默认为50
  • endpoint:该值为 true 时,数列中包含stop值,反之不包含,默认是True。
  • base:对数 log 的底数。
  • dtype:数组的元素类型
a = np.logspace(1, 3, num=3)
print(a)
#[  10.  100. 1000.]

注意:默认是以10为底数的,可以理解为start是10^{start},end为10^{end}

创建对称矩阵

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

创建一个对称矩阵,矩阵的对角线上的值为1,其他值为0。

x = np.eye(5)
print(x)
’’’
[[1. 0. 0. 0. 0.][0. 1. 0. 0. 0.][0. 0. 1. 0. 0.][0. 0. 0. 1. 0.][0. 0. 0. 0. 1.]]
‘’‘

参数说明:

  • N为矩阵的列数
  • M为矩阵的行数,默认等于N
  • k表示对角线1的偏移量
x = np.eye(3, k=1)
print(x)
‘’'
[[0. 1. 0.][0. 0. 1.][0. 0. 0.]]
‘’'x = np.eye(3, k=-1)
print(x)
‘’'
[[0. 0. 0.][1. 0. 0.][0. 1. 0.]]
‘''

 

索引和切片

下标

NumPy数组可以直接通过下标进行访问,下标从0开始,每个下标代表一行数据,下标的下标代表一个元素,也可以直接用逗号分割各维度:

a = np.array([[1,2,3], [10,20,30]])
print(a[1]) #[10 20 30]
print(a[1][1]) #20
print(a[1,1]) #20

切片

NumPy数组也支持切片,通过冒号分隔切片参数 start:stop:step 来进行切片操作。

注意:对切片赋值是直接对数组赋值,会改变数据的值。

一维数组切片

对于一维数组,用法与Python列表一样:

a = np.arange(10)
b = a[2:7:2]   # 从索引 2 开始到索引 7 停止,间隔为 2
print(b) #[2 4 6]
print(a[2]) #2
print(a[2:]) #[2 3 4 5 6 7 8 9]
print(a[:2]) #[0 1]
print(a[2:7]) #[2 3 4 5 6]
print(a[::1]) #[0 1 2 3 4 5 6 7 8 9]
print(a[-2:]) #[8 9]

也支持负整数下标,最后一个数的负整数下标为-1,但因为矩阵比较复杂,而负整数为更进一步的增加表达的复杂度,除非是一维数组,一般不建议使用负整数下标.

冒号 : 的解释:如果只放置一个参数,如 [2],将返回与该索引相对应的单个元素。如果为 [2:],表示从该索引开始以后的所有项都将被提取,如果未[:2],则提取到第2个值(不含2,开区间)。如果使用了两个参数,如 [2:7],那么则提取两个索引(不包括停止索引)之间的项。

如果前面的start和end都不指定,只指定step也是可以的,将根据步长取全部的数据。

多维数组切片

多维数组的切片,对于每一个维度,都是遵循一维的切片规则,不同的维度之间通过逗号分割。

a = np.array([[1,2,3,4], [10,20,30,40], [10, 100, 1000, 10000]])
print(a)
‘’'
[[    1     2     3     4][   10    20    30    40][   10   100  1000 10000]]
‘''print(a[1:])
‘’'
[[   10    20    30    40][   10   100  1000 10000]]
‘’'print(a[:,1:])
‘’'
[[    2     3     4][   20    30    40][  100  1000 10000]]
‘''

如果只想得到某一列,可以通过切片得到,如只想得到第3列:

a = np.array([[1,2,3,4], [10,20,30,40], [10, 100, 1000, 10000]])
print(a[:,2:3])
‘’'
[[   3][  30][1000]]
‘''

如果直接使用第2列的下标,但得到的不是列数据,而是转置为行的数据:

a = np.array([[1,2,3,4], [10,20,30,40], [10, 100, 1000, 10000]])print(a[:,2])
’’’
[   3   30 1000]
‘’‘

如果维度很高,也可以通过...代替前面或后面的维数:

a = np.array([[1,2,3,4], [10,20,30,40], [10, 100, 1000, 10000]])
print(a[...,1]) #第2列元素
# [  2  20 100]
print(a[1,...]) #第2行元素
#[10 20 30 40]
print (a[...,1:])  # 第2列及剩下的所有元素
'''
[[    2     3     4][   20    30    40][  100  1000 10000]]
'''

切片赋值

也可以直接对切片进行赋值,切片是原数组的试图,对切片的赋值,会修改原数组的值。

a = np.array([[11,12,13], [21,22,23],[31,32,33]])
print(a)
‘''
[[11 12 13][21 22 23][31 32 33]]
‘’'print(a[0:2,1]) #[12 22]
a[0,1] = 100
a[0:2,1] = (101,102) #将会修改数组a的元素
print(a[0:2,1]) #[101 102]
print(a)
‘’'
[[ 11 101  13][ 21 102  23][ 31  32  33]]
‘’'b = a[0:2,2]
b[0] = 201 #也同样会修改a的元素
print(a)
’’’
[[ 11 101 201][ 21 102  23][ 31  32  33]]
‘’’b = (301,302) #这个不能修改a的元素,直接把b的引用指向了一个新的元组
print(a)
’’’
[[ 11 101 201][ 21 102  23][ 31  32  33]]
‘’’b = a[0:2,2]
b[:] = (301,302) #如果要修改b的全部元素,要这么样写才行,同样会修改a的元素
print(a)
’’’
[[ 11 101 301][ 21 102 302][ 31  32  33]]
‘’‘

 

整数数组索引

对于多维数组,也可以通过一个整数数组来访问。

以下实例获取数组中 (0,0),(1,1) 和 (2,0) 位置处的元素:

a = np.array([[1,2,3,4], [10,20,30,40], [10, 100, 1000, 10000]])
print(a)
‘’'
[[    1     2     3     4][   10    20    30    40][   10   100  1000 10000]]
‘’'print(a[[0,1,2], [0,1,0]])
‘’'
[ 1 20 10]
‘''

布尔索引(条件过滤)

可以通过布尔索引做条件过滤。直接在中括号中写过滤条件:

x = np.array([[11, 12, 13],[21, 22, 23],[31, 32, 33],[41, 42, 43]])
print(x[x>21]) #[22 23 31 32 33 41 42 43]
print(x[x%2==0]) #[12 22 32 42]
a = np.array([np.nan,  1,2,np.nan,3,4,5])  
print (a[~np.isnan(a)])#[ 1.   2.   3.   4.   5.]

花式索引

花式索引根据索引数组的值作为目标数组的某个轴的下标来取值。

对于使用一维整型数组作为索引,如果目标是一维数组,那么索引的结果就是对应位置的元素,如果目标是二维数组,那么就是对应下标的行。

花式索引跟切片不一样,它总是将数据复制到新数组中。

x = np.array([[11,12,13,14,15],[21,22,23,24,25],[31,32,33,34,35],[41,42,43,44,45], [51,52,53,54,55], [61,62,63,64,65]])
print(x)
print(x[1]) #第2行
print(x[1,2]) #23
print(x[[1,2]]) #第2、3行
print(x[[1,2,3,4],[1,3,2,4]]) #表示获取x(1,1)、(2,3)、(3,2)、(4,4)四个元素,x[]里的第一个中括号是第0维,第2个中括号是第1维。’’’
[[11 12 13 14 15][21 22 23 24 25][31 32 33 34 35][41 42 43 44 45][51 52 53 54 55][61 62 63 64 65]]
[21 22 23 24 25]
23
[[21 22 23 24 25][31 32 33 34 35]]
[22 34 43 55]
‘’‘

从上面的例子可以看出,可以使用x[n]来获得第n+1行的数据,可以通过一个列表作为下标x[[n,m,..]]来获得多行的数据,这就是花式索引。

并且可以用行号重新组织数组,如下:

x = np.array([[11,12,13,14,15],[21,22,23,24,25],[31,32,33,34,35],[41,42,43,44,45], [51,52,53,54,55], [61,62,63,64,65]])
print(x)
print(x[[-1,-2,-3,-4]])‘’'
[[11 12 13 14 15][21 22 23 24 25][31 32 33 34 35][41 42 43 44 45][51 52 53 54 55][61 62 63 64 65]]
[[61 62 63 64 65][51 52 53 54 55][41 42 43 44 45][31 32 33 34 35]]
‘''

广播(数组运算)

广播(Broadcast)是 numpy 对不同维度(shape)的数组进行数值计算的方式, 对数组的算术运算通常在相应的元素上进行。

如果两个数组 a 和 b 形状相同,即满足 a.shape == b.shape,那么 a*b 的结果就是 a 与 b 数组对应位相乘。这要求形状相同(维数相同,且各维度的长度也要相同)。

a = np.array([[1,2,3,4], [7,8,9,10]])
b = np.array([[10,20,30,40], [70,80,90,100]])
c1 = a * b
print(c1)
'''
[[  10   40   90  160][ 490  640  810 1000]]
‘''c2 = a + b
print(c2) 
‘’'
[[ 11  22  33  44][ 77  88  99 110]]
‘''c3 = b - a
print(c3) 
‘’'
[[ 9 18 27 36][63 72 81 90]]
‘''c4 = b / a
print(c4)
‘’'
[[10. 10. 10. 10.][10. 10. 10. 10.]]
‘''

广播不是矩阵运算,是数组各元素按位置与对应另外一个数组的数学运算,将得到与数组一样的维度的数组。

当运算中的 2 个数组的形状不同时,numpy 将自动触发广播机制:

如果两个数组a,b的维数相同,但b的某一个维度或几个维度的长度为1,则会自动将该维度的数据复制进行伸展到与a的形状一致,再进行按元素位置对应的运算。极端情况,b只有一个元素,它可以横向、纵向的任意扩展(复制自己)

例子一:b是一个单一的数,单一的数可以向任何维度复制自己

a = np.array([[11,12,13,14], [21,22,23,24], [31,32,33,34]])
b = 1
c = a + b
print(c)
‘’'
[[12 13 14 15][22 23 24 25][32 33 34 35]]
‘''

例子二:b是一维数据

a = np.array([[11,12,13,14], [21,22,23,24], [31,32,33,34]])
b = np.array([2,2,2,2])
c = a + b
print(c)
‘’'
[[13 14 15 16][23 24 25 26][33 34 35 36]]
‘’'b = np.array([[3],[3],[3]])
c = a + b
print(c)
‘’'
[[14 15 16 17][24 25 26 27][34 35 36 37]]
‘''

无论是纵向还是横向,都会整行(或整列)复制自己。

但是,要求这一维数据的长度必须与a至少一个维度的长度相同,否则会出现

ValueError: operands could not be broadcast together with shapes 

的错误。

a = np.array([[11,12,13,14], [21,22,23,24], [31,32,33,34]])
b = np.array([2,2,2])
c = a + b #ValueError: operands could not be broadcast together with shapes (3,4) (3,) 
print(c)

例子三:三维度的例子

立方体与点的和:a上所有的值都会加上b,形成一个与a形状相同的立方体

a = np.array([[[11,12,13,14],[21,22,23,24],[31,32,33,34]],[[111,112,113,114],[121,122,123,124],[131,132,133,134]],[[211,212,213,214],[221,222,223,224],[231,232,233,234]]])
b = np.array(2)
c = a + b
print(c)’’’
[[[ 13  14  15  16][ 23  24  25  26][ 33  34  35  36]][[113 114 115 116][123 124 125 126][133 134 135 136]][[213 214 215 216][223 224 225 226][233 234 235 236]]]‘’‘

立方体与线段的和:线段会向横和纵两个方向扩展,a的每一组元素对应b的元素的位置进行加和,得到和a一样的形状的数组。

a = np.array([[[11,12,13,14],[21,22,23,24],[31,32,33,34]],[[111,112,113,114],[121,122,123,124],[131,132,133,134]],[[211,212,213,214],[221,222,223,224],[231,232,233,234]]])
# b = np.array(2)
# c = a + b
# print(c)b = np.array([100,101,102,103])
c = a + b
print(c)’’’
[[[111 113 115 117][121 123 125 127][131 133 135 137]][[211 213 215 217][221 223 225 227][231 233 235 237]][[311 313 315 317][321 323 325 327][331 333 335 337]]]
‘’‘

立方体和面的和:按面去加和。

a = np.array([[[11,12,13,14],[21,22,23,24],[31,32,33,34]],[[111,112,113,114],[121,122,123,124],[131,132,133,134]],[[211,212,213,214],[221,222,223,224],[231,232,233,234]]])b = np.array([[100,100,100,100],[200,200,200,200],[300,300,300,300]])
c = a + b
print(c)’’’
[[[111 112 113 114][221 222 223 224][331 332 333 334]][[211 212 213 214][321 322 323 324][431 432 433 434]][[311 312 313 314][421 422 423 424][531 532 533 534]]]
‘’‘

数组的常用方法

NumPy提供了大量操作数组的方法,这里列举几种常用的方法,有些有复杂机制的方法后面还会详细说明。

修改数组形状

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

重新造形

numpy.reshape(newshape, order='C')

该方法在不改变数据的条件下修改形状。

参数说明:

  • newshape:新的形状,可以是一个整数或者整数序列,也可以是展开的多个整数
  • order:'C' -- 按行,'F' -- 按列,'A' -- 原顺序,'k' -- 元素在内存中的出现顺序。
import numpy as npa = np.arange(8)
print('原始数组:')
print(a)
print('\n')b = a.reshape(4, 2)
print('修改后的数组:')
print(b)‘’'
原始数组:
[0 1 2 3 4 5 6 7]修改后的数组:
[[0 1][2 3][4 5][6 7]]
‘''

修改数组大小

numpy.resize(arr, shape)

返回指定大小的新数组,如果新数组大小大于原始大小,则包含原始数组中的元素的副本。

参数说明:

  • arr:要修改大小的数组
  • shape:返回数组的新形状
import numpy as npa = 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]]
’‘’

访问全部元素迭代器

numpy.ndarray.flat

一个数组元素迭代器,可以访问全部的数组元素。

import numpy as npa = 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
‘’‘

展开数组(复制)

ndarray.flatten(order='C')

返回一份数组拷贝并且将多维数组展开,对拷贝所做的修改不会影响原始数组。

参数说明:

  • order:'C' -- 按行,'F' -- 按列,'A' -- 原顺序,'K' -- 元素在内存中的出现顺序。
import numpy as npa = 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]
‘’‘

展开数组(视图)

numpy.ravel(order='C')

返回原数组的展开数组,返回的是数组视图,修改会影响原始数组。

参数说明:

  • order:'C' -- 按行,'F' -- 按列,'A' -- 原顺序,'K' -- 元素在内存中的出现顺序。
import numpy as npa = np.arange(8).reshape(2, 4)
print('原数组a:\n', a)
b = a.flatten()
print('flatten展开的数组b:\n', b)
c = a.ravel()
print ('ravel展开的数组c:\n', c)b[1] = 10
print('修改b[1]后数组b:\n', b)
print('修改b[1]后数组a:\n', a) #a并没有变化
c[1] = 10
print('修改c[1]后数组b:\n', c)
print('修改c[1]后数组a:\n', a) #a的元素值改变了’’’
原数组a:[[0 1 2 3][4 5 6 7]]
flatten展开的数组b:[0 1 2 3 4 5 6 7]
ravel展开的数组c:[0 1 2 3 4 5 6 7]
修改b[1]后数组b:[ 0 10  2  3  4  5  6  7]
修改b[1]后数组a:[[0 1 2 3][4 5 6 7]]
修改c[1]后数组b:[ 0 10  2  3  4  5  6  7]
修改c[1]后数组a:[[ 0 10  2  3][ 4  5  6  7]]
‘’‘

数组变换

函数描述
transpose转置:对换数组的维度
ndarray.T和 self.transpose() 相同
rollaxis向后滚动指定的轴
swapaxes对换数组的两个轴

转置T

numpy.transpose(axes)

返回转置的数组。

参数说明:

  • axes:整数列表,对应维度,通常所有维度都会对换。
a = np.arange(12).reshape(4, 3)
print('原数组a:\n', a)
‘’’
原数组a:[[ 0  1  2][ 3  4  5][ 6  7  8][ 9 10 11]]
’’’print('a转置后:\n', a.transpose())
‘’’
a转置后:[[ 0  3  6  9][ 1  4  7 10][ 2  5  8 11]]
’‘’

可以指定转置的轴,0相当于x轴,1相当于y轴,...,以此类推。上面的例子是二维的,如果指定为tanspose(0,1)相当于没有转置,返回的就是与原来一样的数组,如果是tanspose(1,0)返回的就是转置数组。

a = np.arange(12).reshape(4, 3)
print('原数组a:\n', a)
‘’’
原数组a:[[ 0  1  2][ 3  4  5][ 6  7  8][ 9 10 11]]
’’’print('transpose(0,1):\n', a.transpose(0,1))
‘’’
transpose(0,1):[[ 0  1  2][ 3  4  5][ 6  7  8][ 9 10 11]]
’’’print('transpose(1,0):\n', a.transpose(1,0))
‘’’
transpose(1,0):[[ 0  3  6  9][ 1  4  7 10][ 2  5  8 11]]
’‘’

对于高维数组,可以任意的排列各轴:

a = np.arange(36).reshape(4, 3, 3)
print('原数组a:\n', a)
print('transpose(0,2,1):\n', a.transpose(0,2,1))

也可以直接用numpy.T来表示转置:

a = np.arange(12).reshape(4, 3)
print('原数组a:\n', a)
# print('transpose(0,1):\n', a.transpose(0,1))
print('transpose(1,0):\n', a.transpose(1,0))
print(a.T) #与a.transpose(1,0)相同

滚动轴

numpy.rollaxis(a, axis, start)

向后滚动特定的轴到一个特定位置

参数说明:

  • a:待滚动的数组
  • axis:要向后滚动的轴,其它轴的相对位置不会改变
  • start:默认为零,表示完整的滚动。会滚动到特定位置。

先看二维的情况:

a = np.arange(6).reshape(3, 2)
print(a)
print('滚动轴:\n', np.rollaxis(a, 1))‘’’
[[0 1][2 3][4 5]]
滚动轴:[[0 2 4][1 3 5]]
’‘’

从效果来看就是转置。

再看三维的情况:

a = np.arange(24).reshape(2, 3, 4)
print('原数组a:\n', a)
print('滚动轴:\n', np.rollaxis(a, 1))‘’'
原数组a:[[[ 0  1  2  3][ 4  5  6  7][ 8  9 10 11]][[12 13 14 15][16 17 18 19][20 21 22 23]]]
滚动轴:[[[ 0  1  2  3][12 13 14 15]][[ 4  5  6  7][16 17 18 19]][[ 8  9 10 11][20 21 22 23]]]
‘''

数组(2,3,4)变化为(3,2,4),可以看出0轴和1轴进行了变换。

交换轴

numpy.swapaxes(arr, axis1, axis2)

交换数组的两个轴

参数说明:

  • arr:输入的数组
  • axis1:对应第一个轴的整数
  • axis2:对应第二个轴的整数
a = np.arange(24).reshape(2, 3, 4)
print('原数组a:\n', a)
print('滚动轴:\n', np.rollaxis(a, 1))
print('交换轴:\n', np.swapaxes(a, 1, 0))‘’’
原数组a:[[[ 0  1  2  3][ 4  5  6  7][ 8  9 10 11]][[12 13 14 15][16 17 18 19][20 21 22 23]]]
滚动轴:[[[ 0  1  2  3][12 13 14 15]][[ 4  5  6  7][16 17 18 19]][[ 8  9 10 11][20 21 22 23]]]
交换轴:[[[ 0  1  2  3][12 13 14 15]][[ 4  5  6  7][16 17 18 19]][[ 8  9 10 11][20 21 22 23]]]
’‘’

从上例子可以看到,滚动轴和交换1,0轴是一样的,这两个方法在某些场景有相同的效果。

修改数组维度

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

产生模仿广播的对象

numpy.broadcast(x,y)

扩展y,让它能按照广播的原则按x的形状进行扩展。

numpy.broadcast_to(array, shape, subok=False)

将数组广播到新形状

  • array:要广播的数组
  • shape:新形状
  • subok:如果为True,则为子类,否则默认情况下,返回的数组将被强制为base-class数组

函数将数组广播到新形状。 它在原始数组上返回只 读视图。 它通常不连续。 如果新形状不符合 NumPy 的广播规则,该函数可能会抛出ValueError。

x = np.arange(12).reshape(3, 4)
y = np.array([2,2,2,2])
y1 = np.broadcast_to(y, x.shape)
print(y1)‘’'
[[2 2 2 2][2 2 2 2][2 2 2 2]]
‘''

扩展数组的维度

numpy.expand_dims(arr, axis)

通过在指定位置插入新的轴来扩展数组形状

参数说明:

  • arr:输入数组
  • axis:新轴插入的位置
x = np.array([[11,12],[21,22]])
print('原始数组:\n', x)
y = np.expand_dims(x, axis = 0)
print('插入维度后的数组:\n', y)
y = np.expand_dims(x, axis = 1)
print('插入维度后的数组:\n', y)‘’'
原始数组:[[11 12][21 22]]
插入维度后的数组:[[[11 12][21 22]]]
插入维度后的数组:[[[11 12]][[21 22]]]‘''

删除单维度

numpy.squeeze(arr, axis)

从数组的形状中删除单维度条目,即把shape中为1的维度去掉

参数说明:

  • arr:输入数组
  • axis:整数或整数元组,指定需要删除的维度,但是指定的维度必须为单维度,否则将会报错;axis的取值可为None 或 int 或 tuple of ints, 可选。若axis为空,则删除所有单维度的条目;

x = np.arange(12).reshape(1, 3, 4)
print('原始数组:\n', x)
y = np.squeeze(x)
print('删除1轴后:\n', y)‘’’
原始数组:[[[ 0  1  2  3][ 4  5  6  7][ 8  9 10 11]]]
删除1轴后:[[ 0  1  2  3][ 4  5  6  7][ 8  9 10 11]]
’‘’

连接数组

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

沿轴连接

numpy.concatenate((a1, a2, ...), axis)

函数用于沿指定轴连接相同形状的两个或多个数组

参数说明:

  • a1, a2, ...:相同形状的数组
  • axis:沿着它连接数组的轴,默认为 0
import numpy as npa = 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]]
’‘’
numpy.stack(arrays, axis)

函数用于沿轴连接数组序列

参数说明:

  • arrays相同形状的数组序列
  • axis:返回数组中的轴,输入数组沿着它来堆叠
import numpy as npa = 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]]]
’‘’

水平堆叠

numpy.hstack(arrays)

numpy.stack 函数的变体,它通过水平堆叠来生成数组

import numpy as npa = 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]]
‘''

垂直堆叠

numpy.vstack(arrays)

 numpy.stack 函数的变体,它通过垂直堆叠来生成数组。

import numpy as npa = 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]]
‘''

分割数组

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

沿轴分割

numpy.split(ary, indices_or_sections, axis)

参数说明:

  • ary:被分割的数组
  • indices_or_sections:如果是一个整数,就用该数平均切分,如果是一个数组,为沿轴切分的位置(左开右闭)
  • axis:设置沿着哪个方向进行切分,默认为 0,横向切分,即水平方向。为 1 时,纵向切分,即竖直方向。
import numpy as npa = 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 npa = np.arange(16).reshape(4, 4)
print('第一个数组:')
print(a)print('默认分割(0轴):')
b1,b2 = np.split(a,2)
print('数组1:\n', b1,'\n数组2:\n', b2)print('沿纵向分割:')
c1,c2 = np.split(a,2,1)
print('数组1:\n', c1,'\n数组2:\n', c2)‘’’
第一个数组:
[[ 0  1  2  3][ 4  5  6  7][ 8  9 10 11][12 13 14 15]]
默认分割(0轴):
数组1:[[0 1 2 3][4 5 6 7]] 
数组2:[[ 8  9 10 11][12 13 14 15]]
沿纵向分割:
数组1:[[ 0  1][ 4  5][ 8  9][12 13]] 
数组2:[[ 2  3][ 6  7][10 11][14 15]]
‘''

水平分割

numpy.hsplit(ary, indices_or_sections)

用于水平分割数组,通过指定要返回的相同形状的数组数量来拆分原数组

垂直分割

numpy.vsplit(ary, indices_or_sections)

沿着垂直轴分割,其分割方式与hsplit用法相同。

数组元素的添加与删除

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

末尾添加值

numpy.append(arr, values, axis=None)

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

参数说明:

  • arr:输入数组
  • values:要向arr添加的值,需要和arr形状相同(除了要添加的轴)
  • axis:默认为 None。当axis无定义时,是横向加成,返回总是为一维数组!当axis有定义的时候,分别为0和1的时候(列数要相同)。当axis为1时,数组是加在右边(行数要相同)。
import numpy as npa = np.array([[1, 2, 3], [4, 5, 6]])print('第一个数组:\n', a)print('向数组添加元素:')
print(np.append(a, [7, 8, 9]))print('沿轴 0 添加元素:')
print(np.append(a, [[7, 8, 9]], axis=0))print('沿轴 1 添加元素:')
print(np.append(a, [[10, 11, 12], [21, 22, 23]], 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 10 11 12][ 4  5  6 21 22 23]]
’‘’

按索引插入值

numpy.insert(arr, obj, values, axis)

在给定索引之前,沿给定轴在输入数组中插入值,将返回一个新数组。如果未提供轴,则输入数组会被展开。

参数说明:

  • arr:输入数组
  • obj:在其之前插入值的索引
  • values:要插入的值
  • axis:沿着它插入的轴,如果未提供,则输入数组会被展开;传递了 Axis 参数。 会广播值数组来配输入数组。
import numpy as npa = np.arange(12).reshape(3,4)
print('第一个数组:\n', a)
print('未传递 Axis 参数。 在3前插入[100, 200]之前输入数组会被展开。')
print(np.insert(a, 3, [100, 200]))#传递了 Axis 参数。 会广播值数组来配输入数组
print('指定0轴的2行(0行开始)前插入[100,101,102,103]:')
print(np.insert(a, 2, [100,101,102,103], axis=0))
print('指定0轴的2行(0行开始)前插入[100],按广播扩展:')
print(np.insert(a, 2, [100], axis=0))print('指定1轴的3列前插入[100,101,102](会自动转置):')
print(np.insert(a, 3, [100,101,102], axis=1))
print('指定1轴的3列前插入[100],按广播扩展:')
print(np.insert(a, 3, 100, axis=1))‘’’
第一个数组:[[ 0  1  2  3][ 4  5  6  7][ 8  9 10 11]]
未传递 Axis 参数。 在3前插入[100, 200]之前输入数组会被展开。
[  0   1   2 100 200   3   4   5   6   7   8   9  10  11]
指定0轴的2行(0行开始)前插入[100,101,102,103]:
[[  0   1   2   3][  4   5   6   7][100 101 102 103][  8   9  10  11]]
指定0轴的2行(0行开始)前插入[100],按广播扩展:
[[  0   1   2   3][  4   5   6   7][100 100 100 100][  8   9  10  11]]
指定1轴的3列前插入[100,101,102](会自动转置):
[[  0   1   2 100   3][  4   5   6 101   7][  8   9  10 102  11]]
指定1轴的3列前插入[100],按广播扩展:
[[  0   1   2 100   3][  4   5   6 100   7][  8   9  10 100  11]]
’‘’

删除指定子数组

Numpy.delete(arr, obj, axis)

返回从输入数组中删除指定子数组的新数组,与 insert() 函数的情况一样,如果未提供轴参数,则输入数组将展开。

参数说明:

  • arr:输入数组
  • obj:可以被切片,整数或者整数数组,表明要从输入数组删除的子数组
  • axis:沿着它删除给定子数组的轴,如果未提供,则输入数组会被展开
import numpy as npa = np.arange(12).reshape(3,4)
print('第一个数组:\n', a)
print('删除元素5,未传递 Axis 参数,在插入之前输入数组会被展开。')
print(np.delete(a, 5))print('如果指定轴1,删除第二列:')
print(np.delete(a, 1, axis=1))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]]
删除元素5,未传递 Axis 参数,在插入之前输入数组会被展开。
[ 0  1  2  3  4  6  7  8  9 10 11]
如果指定轴1,删除第二列:
[[ 0  2  3][ 4  6  7][ 8 10 11]]
包含从数组中删除的替代值的切片:
[ 2  4  6  8 10]
’‘’

数组去重

numpy.unique(arr, return_index, return_inverse, return_counts)

返回见下面的说明

参数说明:

  • arr:输入数组,如果不是一维数组则会展开
  • return_index:如果为true,返回新列表元素在旧列表中的位置(下标),并以列表形式储
  • return_inverse:如果为true,返回旧列表元素在新列表中的位置(下标),并以列表形式储
  • return_counts:如果为true,返回去重数组中的元素在原数组中的出现次数
import numpy as npa = np.array([[1,2,3,4],[1,2,3,4],[4,5,6,7]])
print('待去重的数组:\n', a)print('去重:\n', np.unique(a))print('去重索引数组:')
u, indices = np.unique(a, return_index=True)
print(indices)print('去重下标:')
u, indices = np.unique(a, return_inverse=True)
print(indices)print('返回去重元素的重复数量:')
u, indices = np.unique(a, return_counts=True)
print(indices)‘’'
待去重的数组:[[1 2 3 4][1 2 3 4][4 5 6 7]]
去重:[1 2 3 4 5 6 7]
去重索引数组:
[ 0  1  2  3  9 10 11]
去重下标:
[0 1 2 3 0 1 2 3 3 4 5 6]
返回去重元素的重复数量:
[2 2 2 3 1 1 1]
‘''

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.rhkb.cn/news/148837.html

如若内容造成侵权/违法违规/事实不符,请联系长河编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

5个适合初学者的初级网络安全工作,网络安全就业必看

前言 网络安全涉及保护计算机系统、网络和数据免受未经授权的访问、破坏和盗窃 - 防止数字活动和数据访问的中断 - 同时也保护用户的资产和隐私。鉴于公共事业、医疗保健、金融以及联邦政府等行业的网络犯罪攻击不断升级&#xff0c;对网络专业人员的需求很高&#xff0c;这并…

Linux系统编程系列之线程池

Linux系统编程系列&#xff08;16篇管饱&#xff0c;吃货都投降了&#xff01;&#xff09; 1、Linux系统编程系列之进程基础 2、Linux系统编程系列之进程间通信(IPC)-信号 3、Linux系统编程系列之进程间通信(IPC)-管道 4、Linux系统编程系列之进程间通信-IPC对象 5、Linux系统…

IPsec_SSL VPN身份鉴别过程简要

一、IPsec VPN身份鉴别&#xff08;参考国密标准《GMT 0022-2014 IPsec VPN技术规范》&#xff09; IKE第一阶段&#xff08;主模式&#xff09; “消息2”由响应方发出&#xff0c;消息中具体包含一个SA载荷&#xff08;确认所接受的SA提议&#xff09;、响应方的签名证书和…

Jmeter排查正则表达式提取器未生效问题

今天在使用Jmeter的时候遇到一个很简单的问题&#xff0c;使用正则表达式提取token一直未生效&#xff0c;原因是正则表达式中多了一个空格。虽然问题很简单&#xff0c;但是觉得排查问题的方法很普适&#xff0c;所以记录下&#xff0c;也希望能够给遇到问题的大家一个参考。 …

制作 3 档可调灯程序编写

PWM 0~255 可以将数据映射到0 75 150 225 尽可能均匀电压间隔

很普通的四非生,保研破局经验贴

推免之路 个人情况简介夏令营深圳大学情况机试面试结果 预推免湖南师范大学面试结果 安徽大学面试结果 北京科技大学笔试面试结果 合肥工业大学南京航空航天大学面试结果 暨南大学东北大学 最终结果一些建议写在后面 个人情况简介 教育水平&#xff1a;某中医药院校的医学信息…

计算机网络(第8版)-第4章 网络层

4.1 网络层的几个重要概念 4.1.1 网络层提供的两种服务 如果主机&#xff08;即端系统&#xff09;进程之间需要进行可靠的通信&#xff0c;那么就由主机中的运输层负责&#xff08;包括差错处理、流量控制等&#xff09;。 4.1.2 网络层的两个层面 4.2 网际协议 IP 图4-4 网…

PyTorch实例:简单线性回归的训练和反向传播解析

文章目录 &#x1f966;引言&#x1f966;什么是反向传播&#xff1f;&#x1f966;反向传播的实现&#xff08;代码&#xff09;&#x1f966;反向传播在深度学习中的应用&#x1f966;链式求导法则&#x1f966;总结 &#x1f966;引言 在神经网络中&#xff0c;反向传播算法…

【Java 进阶篇】JDBC 数据库连接池 C3P0 详解

数据库连接池是数据库编程中常用的一种技术&#xff0c;它可以有效地管理数据库连接&#xff0c;提高数据库访问的性能和效率。在 Java 编程中&#xff0c;有多种数据库连接池可供选择&#xff0c;其中之一就是 C3P0。本文将详细介绍 C3P0 数据库连接池的使用&#xff0c;包括原…

linux内核分析:网络协议栈

从本质上来讲,所谓的建立连接,其实是为了在客户端和服务端维护连接,而建立一定的数据结构来维护双方交互的状态,并用这样的数据结构来保证面向连接的特性。TCP 无法左右中间的任何通路,也没有什么虚拟的连接,中间的通路根本意识不到两端使用了 TCP 还是 UDP。 所谓的连接…

redis持久化与调优

一 、Redis 高可用&#xff1a; 在web服务器中&#xff0c;高可用是指服务器可以正常访问的时间&#xff0c;衡量的标准是在多长时间内可以提供正常服务&#xff08;99.9%、99.99%、99.999%等等&#xff09;。但是在Redis语境中&#xff0c;高可用的含义似乎要宽泛一些&#x…

OpenCV利用Camshift实现目标追踪

目录 原理 做法 代码实现 结果展示 原理 做法 代码实现 import numpy as np import cv2 as cv# 读取视频 cap cv.VideoCapture(video.mp4)# 检查视频是否成功打开 if not cap.isOpened():print("Error: Cannot open video file.")exit()# 获取第一帧图像&#x…

【赠书活动第3期】《构建新型网络形态下的网络空间安全体系》——用“价值”的视角来看安全

目录 一、内容简介二、读者受众三、图书目录四、编辑推荐五、获奖名单 一、内容简介 经过30多年的发展&#xff0c;安全已经深入到信息化的方方面面&#xff0c;形成了一个庞大的产业和复杂的理论、技术和产品体系。 因此&#xff0c;需要站在网络空间的高度看待安全与网络的…

UE5报错及解决办法

1、编译报错&#xff0c;内容如下&#xff1a; Unable to build while Live Coding is active. Exit the editor and game, or press CtrlAltF11 if iterating on code in the editor or game 解决办法 取消Enable Live Coding勾选

企业部署,springboot+vue+vue,Linux上部署mysql与redis,docker中部署nginx,jenkins。完整详细。

企业项目部署全流程笔记 前言 涉及&#xff1a;Linux服务器&#xff0c;docker&#xff0c;Jenkins&#xff0c;nginx&#xff0c;springoot&#xff0c;vue&#xff0c;mysql&#xff0c;redis&#xff0c;git&#xff0c; docker生成容器类型&#xff1a;MySql&#xff0c…

string类的模拟实现(万字讲解超详细)

目录 前言 1.命名空间的使用 2.string的成员变量 3.构造函数 4.析构函数 5.拷贝构造 5.1 swap交换函数的实现 6.赋值运算符重载 7.迭代器部分 8.数据容量控制 8.1 size和capacity 8.2 empty 9.数据修改部分 9.1 push_back 9.2 append添加字符串 9.3 运算符重载…

[学习笔记]ARXML - Data Format

参考AUTOSAR文档&#xff1a; https://www.autosar.org/fileadmin/standards/R22-11/FO/AUTOSAR_TPS_ARXMLSerializationRules.pdfhttps://www.autosar.org/fileadmin/standards/R22-11/FO/AUTOSAR_TPS_ARXMLSerializationRules.pdf 编码 arxml只允许使用UTF-8编码&#xff…

小谈设计模式(19)—备忘录模式

小谈设计模式&#xff08;19&#xff09;—备忘录模式 专栏介绍专栏地址专栏介绍 备忘录模式主要角色发起人&#xff08;Originator&#xff09;备忘录&#xff08;Memento&#xff09;管理者&#xff08;Caretaker&#xff09; 应用场景结构实现步骤Java程序实现首先&#xff…

VC++创建windows服务程序

目录 1.关于windows标准可执行程序和服务程序 2.服务相关整理 2.1 VC编写服务 2.2 服务注册 2.3 服务卸载 2.4 启动服务 2.5 关闭服务 2.6 sc命令 2.7 查看服务 3.标准程序 3.1 后台方式运行标准程序 3.2 查找进程 3.3 终止进程 以前经常在Linux下编写服务器程序…

小程序中如何开启分销

小程序共享微信生态&#xff0c;商家可以通过小程序来快速扩大自己的销售渠道&#xff0c;其中一个非常受重要的功能就是分销。通过开启分销功能&#xff0c;商家可以让更多的人参与到销售中来&#xff0c;从而提高销售额。那么&#xff0c;在小程序中如何开启设置分销呢&#…