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.xdnf.cn/news/149405.html

如若内容造成侵权/违法违规/事实不符,请联系一条长河网进行投诉反馈,一经查实,立即删除!

相关文章

2023.10.5 文件操作IO 经典例题

目录 例题一 例题二 例题一 扫描指定目录&#xff0c;并找到名称中包含指定字符的所有普通文件&#xff08;不包含目录&#xff09;&#xff0c;并且后续询问用户是否删除该文件 代码如下&#xff1a; package io;import java.io.File; import java.util.Scanner;//扫描指定目…

RSA攻击:模数分解

目录 一、模数分解总览 1.1直接分解法 1.2费马分解与Pollard_rho分解 1.3公约数分解 1.4其他模数分解 二、实战特训 2.1[黑盾杯 2020]Factor 2.2[GWCTF 2019]babyRSA 2.3[LitCTF 2023]yafu (中级) 2.4[RoarCTF 2019]RSA 2.5[CISCN 2022 西南]rsa 三、总结 一、模数分解总览 …

使用idea 中的rest 将 git 合并部分分支代码到主分支

需求&#xff1a;当要将dev的分支中的部分代码合并到test分支时&#xff0c;又不想把dev的全部代码合并到test分支 例如dev分支已经提交了 demo1到4&#xff0c;到想把demo1-3的代码合并到test分支&#xff0c;demo4暂时不合并 可以使用idea的reset 功能满足以上需求 1首先切…

Seata 源码篇之AT模式启动流程 - 中 - 03

Seata 源码篇之AT模式启动流程 - 中 - 03 数据源代理会话代理锁定查询执行器本地事务提交本地事务回滚 更新执行器删除执行器插入执行器 小节 本系列文章: Seata 源码篇之核心思想 - 01Seata 源码篇之AT模式启动流程 - 上 - 02 数据源代理 当我们的数据源被代理后&#xff0c…

.Net开源迁移框架FluentMigrator的使用。

在实际的开发过程中&#xff0c;经常会遇到数据库结构变动&#xff0c;比如新增表、删除表&#xff1b;已有的表新增字段&#xff0c;删除字段&#xff1b;修改字段属性等等。而且需要开发环境、测试环境和生产环境进行同步。如果使用的是EF&#xff0c;还是挺方便的。而非EF环…

PyTorch入门之【tensor】

目录 tensor的创建tensor的相关信息tensor的运算 tensor的创建 1.手动创建 import torch test1torch.tensor([1,2,3])#一维时为向量 test2torch.tensor([[1,2,3]])#二维时为矩阵 test3torch.tensor([[[1,2,3]]])#三维及以上统称为tensor print(test1) print(test2) print(tes…

【Linux】线程详解完结篇——信号量 + 线程池 + 单例模式 + 读写锁

线程详解第四篇 前言正式开始信号量引例信号量的本质信号量相关的四个核心接口生产消费者模型用环形队列实现生产者消费者模型基于环形队列的生产消费模型的原理代码演示单生产者单消费者多生产者多消费者 计数器的意义 线程池基本概念代码 单例模式STL,智能指针和线程安全STL中…

文心一言 VS 讯飞星火 VS chatgpt (106)-- 算法导论10.1 4题

四、用go语言&#xff0c;重写 ENQUEUE 和 DEQUEUE 的代码&#xff0c;使之能处理队列的下溢和上溢。 文心一言&#xff1a; 在 Go 语言中&#xff0c;我们可以使用切片来实现队列。下面是如何实现 ENQUEUE 和 DEQUEUE 操作&#xff0c;同时处理队列的下溢和上溢的情况&#…

git提交代码的流程

1.拉取代码 当你进入了一家公司就需要拉去公司的代码进行开发,此时你的项目小组长会给你个地址拉代码, git clone 公司项目的地址 此时如果不使用了这个方式拉去代码,拉去的是master分支上的代码,但是很多数的情况下&#xff0c;公司的项目可能会在其它的分支上,因此到公…

经典算法-----汉诺塔问题

前言 今天我们学习一个老经典的问题-----汉诺塔问题&#xff0c;可能在学习编程之前我们就听说过这个问题&#xff0c;那这里我们如何去通过编程的方式去解决这么一个问题呢&#xff1f;下面接着看。 汉诺塔问题 问题描述 这里是引用汉诺塔问题源自印度一个古老的传说&#x…

Python3数据科学包系列(一):数据分析实战

Python3中类的高级语法及实战 Python3(基础|高级)语法实战(|多线程|多进程|线程池|进程池技术)|多线程安全问题解决方案 Python3数据科学包系列(一):数据分析实战 Python3数据科学包系列(二):数据分析实战 认识下数据科学中数据处理基础包: (1)NumPy 俗话说: 要学会跑需先…

<C++>类和对象-下

目录 一、构造函数的初始化 1. 构造函数体赋值 2. 初始化列表 2.1 概念 2.2 隐式类型转换式构造 2.3 explicit关键字 二、static静态成员 1. 概念 2. 特性 三、友元 1. 友元函数 2.友元类 四、内部类 1. 概念 五、匿名对象 1. const引用匿名对象 2. 匿名对象的隐式类型转换 总…

postgresql实现单主单从

实现步骤 1.主库创建一个有复制权限的用户 CREATE ROLE 用户名login # 有登录权限的角色即是用户replication #复制权限 encrypted password 密码;2.主库配置开放从库外部访问权限 修改 pg_hba.conf 文件 &#xff08;相当于开放防火墙&#xff09; # 类型 数据库 …

Swing程序设计(5)绝对布局,流布局

文章目录 前言一、布局管理器二、介绍 1.绝对布局2.流布局总结 前言 Swing窗体中&#xff0c;每一个组件都有大小和具体的位置。而在容器中摆放各种组件时&#xff0c;很难判断其组件的具体位置和大小。即一个完整的界面中&#xff0c;往往有多个组件&#xff0c;那么如何将这…

Unity如何实现TreeView

前言 最近有一个需求,需要实现一个TreeView的试图显示,开始我一直觉得这么通用的结构,肯定有现成的UI组件或者插件可以使用,结果,找了好久,都没有找到合适的插件,有两个效果差强人意。 最后在回家的路上突然灵光一闪,想到了一种简单的实现方式,什么插件都不用,仅使用…

基于虚拟同步发电机控制的双机并联Simulink仿真模型

&#x1f4a5;&#x1f4a5;&#x1f49e;&#x1f49e;欢迎来到本博客❤️❤️&#x1f4a5;&#x1f4a5; &#x1f3c6;博主优势&#xff1a;&#x1f31e;&#x1f31e;&#x1f31e;博客内容尽量做到思维缜密&#xff0c;逻辑清晰&#xff0c;为了方便读者。 ⛳️座右铭&a…

1024 科学计数法

一.问题&#xff1a; 科学计数法是科学家用来表示很大或很小的数字的一种方便的方法&#xff0c;其满足正则表达式 [-][1-9].[0-9]E[-][0-9]&#xff0c;即数字的整数部分只有 1 位&#xff0c;小数部分至少有 1 位&#xff0c;该数字及其指数部分的正负号即使对正数也必定明确…

kafka集群工作机制

一、kafka在zookeeper上的元数据解释 kafka中的broker要选举Controller角色来管理整个kafka集群中的分区和副本状态。一个Topic下多个partition要选举Leader角色和客户端进行交互数据 Zookeeper客户端工具&#xff1a; prettyZoo。 下载地址&#xff1a;https://github.com/vr…

2023年R1快开门式压力容器操作证模拟考试题库及R1快开门式压力容器操作理论考试试题

题库来源&#xff1a;安全生产模拟考试一点通公众号小程序 2023年R1快开门式压力容器操作证模拟考试题库及R1快开门式压力容器操作理论考试试题是由安全生产模拟考试一点通提供&#xff0c;R1快开门式压力容器操作证模拟考试题库是根据R1快开门式压力容器操作最新版教材&#…