• Python的NumPy库(一)基础用法


    Python开发实用教程

    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是通过嵌套几层中括号来表示的,形状是通过中括号里的元素个数来表示的(中括号里的每一个中括号也是一个元素)。

    1. a = np.array([[1,2,3,4], [10,20+5j,30+1j,40+2j]])
    2. print(a)
    3. print(a.ndim) #2
    4. print(a.shape) #(2, 4)
    5. print(a.dtype) #int64
    6. print(a.itemsize) #8
    7. print(a.flags)
    8. # C_CONTIGUOUS: True
    9. # F_CONTIGUOUS: False
    10. # OWNDATA: True
    11. # WRITEABLE: True
    12. # ALIGNED: True
    13. # WRITEBACKIFCOPY: False
    14. print(a.real)
    15. #[[ 1. 2. 3. 4.]
    16. # [10. 20. 30. 40.]]
    17. print(a.imag)
    18. #[[0. 0. 0. 0.]
    19. # [0. 5. 1. 2.]]
    20. print(a.data)
    21. #

    基于序列类型创建数组

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

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

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

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

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

    1. import numpy as np
    2. a = np.array([1,2,3,4,2])
    3. print(a) #[1 2 3 4 2]
    4. print(a.dtype) #int64
    5. a = np.array([1,2,3,4,2.0])
    6. print(a) #[1. 2. 3. 4. 2.]
    7. print(a.dtype) #float64
    8. a = np.array([1,2,3,4,'ab'])
    9. print(a.dtype) #
    10. print(a) #['1' '2' '3' '4' 'ab']

    元素也可以支持字典:

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

    元素也支持自定义对象

    1. class MyClass:
    2. def __init__(self, a, b):
    3. self.a = a
    4. self.b = b
    5. def __repr__(self):
    6. return f'(MyClass {self.a=}, {self.b=})'
    7. def foo(self):
    8. pass
    9. c = np.array([MyClass(1, 2), MyClass('s', 'c')])
    10. print(c) #[(MyClass self.a=1, self.b=2) (MyClass self.a='s', self.b='c')]
    11. print(c.dtype) #object

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

    1. c = np.array([MyClass(1, 2), MyClass('s', 'c'), MyClass2(), {2:'2', 3:'3'}])
    2. 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'}]
    3. print(c.dtype) #object

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

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

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

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

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

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

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

    1. c = np.array((20,30,40,50), ndmin=2, dtype=complex)
    2. print(c)
    3. #[[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,则是对内置数据类型对象的引用
    1. dt = np.dtype(np.int32)
    2. print(dt)
    3. #int32
    4. dt = np.dtype('i4')
    5. print(dt)
    6. #int32
    7. dt = np.dtype(')
    8. print(dt)
    9. #int32

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

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

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

    1. STUDENT = np.dtype([('name','S20'), ('age', 'i1'), ('marks', 'f4')])
    2. print(STUDENT)
    3. #[('name', 'S20'), ('age', 'i1'), ('marks', '
    4. a = np.array([('John', 12, 91.5),('Rose', 13, 99)], dtype = STUDENT)
    5. print(a)
    6. #[(b'John', 12, 91.5) (b'Rose', 13, 99. )]
    7. print(a.dtype)
    8. #[('name', 'S20'), ('age', 'i1'), ('marks', '

    从上面的例子可以看出,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()的视图相当于新增加了一个指向当前内存的引用,不存在复制操作,速度更快且节约内存。注意通过其中的一个引用修改数据,其他引用的数据也会跟着变,因为他们指向同一块内存区域。
    1. a1 = np.asarray([[1, 2, 3], [4, 5, 6]])
    2. print(f'{a1=}')
    3. b1 = np.asarray(a1)
    4. print(f'{b1=}')
    5. b2 = np.array(a1)
    6. print(f'{b2=}')
    7. a1[1][1] = 10
    8. print('-------')
    9. print(f'{a1=}')
    10. print(f'{b1=}')
    11. print(f'{b2=}’)
    12. ‘’'
    13. a1=array([[1, 2, 3],
    14. [4, 5, 6]])
    15. b1=array([[1, 2, 3],
    16. [4, 5, 6]])
    17. b2=array([[1, 2, 3],
    18. [4, 5, 6]])
    19. -------
    20. a1=array([[ 1, 2, 3],
    21. [ 4, 10, 6]])
    22. b1=array([[ 1, 2, 3],
    23. [ 4, 10, 6]])
    24. b2=array([[1, 2, 3],
    25. [4, 5, 6]])
    26. ''

    指定形状的创建

    创建空数组

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

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

    参数说明:

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

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

    创建0填充数组

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

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

    参数说明:

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

    创建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来填充。

    1. x = np.full((3,2), 'OK')
    2. print(x)
    3. ’’’
    4. [['OK' 'OK']
    5. ['OK' 'OK']
    6. ['OK' 'OK’]]
    7. ‘’‘

    仿制数组

    仿制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 数组的形状。
    1. a = np.array([[1, 2, 3], [4, 5, 6], [7, 8, 9]])
    2. za = np.zeros_like(a)
    3. print(za)
    4. ‘’'
    5. [[0 0 0]
    6. [0 0 0]
    7. [0 0 0]]
    8. ‘''

    仿制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
    1. bs = b'This is a test case!'
    2. a = np.frombuffer(bs, dtype='S2')
    3. print(a)
    4. #[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,读取所有数据。
    1. it = iter(range(5))
    2. x = np.fromiter(it, dtype=int)
    3. print(x) #[0 1 2 3 4]

    创建范围数组

    类似于Python的range:

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

    参数说明:

    • start:起始值,创建的数组包含这个数(闭区间)
    • stop:终止值,创建的数组将不包含这个数(开区间)
    • step:步长,默认是1
    • dtype:数组的元素类型,如果没有提供,则会使用输入数据的类型。
    1. import numpy as np
    2. x = np.arange(5)
    3. 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的增强版本。

    1. a = np.linspace(10, 15, num=6, dtype=float)
    2. print(a) #[10. 11. 12. 13. 14. 15.]
    3. a = np.linspace(10, 20, num=6, dtype=float)
    4. print(a) #[10. 12. 14. 16. 18. 20.]
    5. a = np.linspace(10, 20, num=6, endpoint=False, dtype=float)
    6. print(a) #[10. 11.66666667 13.33333333 15. 16.66666667 18.33333333]
    7. #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
    8. a = np.linspace(10, 19, num=6, endpoint=False, dtype=float)
    9. 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:数组的元素类型
    1. a = np.logspace(1, 3, num=3)
    2. print(a)
    3. #[ 10. 100. 1000.]

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

    创建对称矩阵

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

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

    1. x = np.eye(5)
    2. print(x)
    3. ’’’
    4. [[1. 0. 0. 0. 0.]
    5. [0. 1. 0. 0. 0.]
    6. [0. 0. 1. 0. 0.]
    7. [0. 0. 0. 1. 0.]
    8. [0. 0. 0. 0. 1.]]
    9. ‘’‘

    参数说明:

    • N为矩阵的列数
    • M为矩阵的行数,默认等于N
    • k表示对角线1的偏移量
    1. x = np.eye(3, k=1)
    2. print(x)
    3. ‘’'
    4. [[0. 1. 0.]
    5. [0. 0. 1.]
    6. [0. 0. 0.]]
    7. ‘’'
    8. x = np.eye(3, k=-1)
    9. print(x)
    10. ‘’'
    11. [[0. 0. 0.]
    12. [1. 0. 0.]
    13. [0. 1. 0.]]
    14. ‘''

    索引和切片

    下标

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

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

    切片

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

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

    一维数组切片

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

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

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

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

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

    多维数组切片

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

    1. a = np.array([[1,2,3,4], [10,20,30,40], [10, 100, 1000, 10000]])
    2. print(a)
    3. ‘’'
    4. [[ 1 2 3 4]
    5. [ 10 20 30 40]
    6. [ 10 100 1000 10000]]
    7. ‘''
    8. print(a[1:])
    9. ‘’'
    10. [[ 10 20 30 40]
    11. [ 10 100 1000 10000]]
    12. ‘’'
    13. print(a[:,1:])
    14. ‘’'
    15. [[ 2 3 4]
    16. [ 20 30 40]
    17. [ 100 1000 10000]]
    18. ''

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

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

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

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

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

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

    切片赋值

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

    1. a = np.array([[11,12,13], [21,22,23],[31,32,33]])
    2. print(a)
    3. ''
    4. [[11 12 13]
    5. [21 22 23]
    6. [31 32 33]]
    7. ‘’'
    8. print(a[0:2,1]) #[12 22]
    9. a[0,1] = 100
    10. a[0:2,1] = (101,102) #将会修改数组a的元素
    11. print(a[0:2,1]) #[101 102]
    12. print(a)
    13. ‘’'
    14. [[ 11 101 13]
    15. [ 21 102 23]
    16. [ 31 32 33]]
    17. ‘’'
    18. b = a[0:2,2]
    19. b[0] = 201 #也同样会修改a的元素
    20. print(a)
    21. ’’’
    22. [[ 11 101 201]
    23. [ 21 102 23]
    24. [ 31 32 33]]
    25. ‘’’
    26. b = (301,302) #这个不能修改a的元素,直接把b的引用指向了一个新的元组
    27. print(a)
    28. ’’’
    29. [[ 11 101 201]
    30. [ 21 102 23]
    31. [ 31 32 33]]
    32. ‘’’
    33. b = a[0:2,2]
    34. b[:] = (301,302) #如果要修改b的全部元素,要这么样写才行,同样会修改a的元素
    35. print(a)
    36. ’’’
    37. [[ 11 101 301]
    38. [ 21 102 302]
    39. [ 31 32 33]]
    40. ‘’‘

    整数数组索引

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

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

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

    布尔索引(条件过滤)

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

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

    花式索引

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

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

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

    1. 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]])
    2. print(x)
    3. print(x[1]) #第2行
    4. print(x[1,2]) #23
    5. print(x[[1,2]]) #第2、3行
    6. print(x[[1,2,3,4],[1,3,2,4]]) #表示获取x(1,1)、(2,3)、(3,2)、(4,4)四个元素,x[]里的第一个中括号是第0维,第2个中括号是第1维。
    7. ’’’
    8. [[11 12 13 14 15]
    9. [21 22 23 24 25]
    10. [31 32 33 34 35]
    11. [41 42 43 44 45]
    12. [51 52 53 54 55]
    13. [61 62 63 64 65]]
    14. [21 22 23 24 25]
    15. 23
    16. [[21 22 23 24 25]
    17. [31 32 33 34 35]]
    18. [22 34 43 55]
    19. ‘’‘

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

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

    1. 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]])
    2. print(x)
    3. print(x[[-1,-2,-3,-4]])
    4. ‘’'
    5. [[11 12 13 14 15]
    6. [21 22 23 24 25]
    7. [31 32 33 34 35]
    8. [41 42 43 44 45]
    9. [51 52 53 54 55]
    10. [61 62 63 64 65]]
    11. [[61 62 63 64 65]
    12. [51 52 53 54 55]
    13. [41 42 43 44 45]
    14. [31 32 33 34 35]]
    15. ‘''

    广播(数组运算)

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

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

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

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

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

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

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

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

    例子二:b是一维数据

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

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

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

    ValueError: operands could not be broadcast together with shapes 

    的错误。

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

    例子三:三维度的例子

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

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

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

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

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

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

    数组的常用方法

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

    修改数组形状

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

    重新造形

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

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

    参数说明:

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

    修改数组大小

    numpy.resize(arr, shape)

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

    参数说明:

    • arr:要修改大小的数组
    • shape:返回数组的新形状
    1. import numpy as np
    2. a = np.array([[1,2,3],[4,5,6]])
    3. print ('第一个数组:')
    4. print (a)
    5. print ('\n')
    6. print ('第一个数组的形状:')
    7. print (a.shape)
    8. print ('\n')
    9. b = np.resize(a, (3,2))
    10. print ('第二个数组:')
    11. print (b)
    12. print ('\n')
    13. print ('第二个数组的形状:')
    14. print (b.shape)
    15. print ('\n')
    16. # 要注意 a 的第一行在 b 中重复出现,因为尺寸变大了
    17. print ('修改第二个数组的大小:')
    18. b = np.resize(a,(3,3))
    19. print (b)
    20. ‘’’
    21. 第一个数组:
    22. [[1 2 3]
    23. [4 5 6]]
    24. 第一个数组的形状:
    25. (2, 3)
    26. 第二个数组:
    27. [[1 2]
    28. [3 4]
    29. [5 6]]
    30. 第二个数组的形状:
    31. (3, 2)
    32. 修改第二个数组的大小:
    33. [[1 2 3]
    34. [4 5 6]
    35. [1 2 3]]
    36. ’‘’

    访问全部元素迭代器

    numpy.ndarray.flat

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

    1. import numpy as np
    2. a = np.arange(9).reshape(3,3)
    3. print ('原始数组:')
    4. for row in a:
    5. print (row)
    6. #对数组中每个元素都进行处理,可以使用flat属性,该属性是一个数组元素迭代器:
    7. print ('迭代后的数组:')
    8. for element in a.flat:
    9. print (element)
    10. ’’’
    11. 原始数组:
    12. [0 1 2]
    13. [3 4 5]
    14. [6 7 8]
    15. 迭代后的数组:
    16. 0
    17. 1
    18. 2
    19. 3
    20. 4
    21. 5
    22. 6
    23. 7
    24. 8
    25. ‘’‘

    展开数组(复制)

    ndarray.flatten(order='C')

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

    参数说明:

    • order:'C' -- 按行,'F' -- 按列,'A' -- 原顺序,'K' -- 元素在内存中的出现顺序。
    1. import numpy as np
    2. a = np.arange(8).reshape(2,4)
    3. print ('原数组:')
    4. print (a)
    5. print ('\n')
    6. # 默认按行
    7. print ('展开的数组:')
    8. print (a.flatten())
    9. print ('\n')
    10. print ('以 F 风格顺序展开的数组:')
    11. print (a.flatten(order = 'F’))
    12. ’’’
    13. 原数组:
    14. [[0 1 2 3]
    15. [4 5 6 7]]
    16. 展开的数组:
    17. [0 1 2 3 4 5 6 7]
    18. 以 F 风格顺序展开的数组:
    19. [0 4 1 5 2 6 3 7]
    20. ‘’‘

    展开数组(视图)

    numpy.ravel(order='C')

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

    参数说明:

    • order:'C' -- 按行,'F' -- 按列,'A' -- 原顺序,'K' -- 元素在内存中的出现顺序。
    1. import numpy as np
    2. a = np.arange(8).reshape(2, 4)
    3. print('原数组a:\n', a)
    4. b = a.flatten()
    5. print('flatten展开的数组b:\n', b)
    6. c = a.ravel()
    7. print ('ravel展开的数组c:\n', c)
    8. b[1] = 10
    9. print('修改b[1]后数组b:\n', b)
    10. print('修改b[1]后数组a:\n', a) #a并没有变化
    11. c[1] = 10
    12. print('修改c[1]后数组b:\n', c)
    13. print('修改c[1]后数组a:\n', a) #a的元素值改变了
    14. ’’’
    15. 原数组a:
    16. [[0 1 2 3]
    17. [4 5 6 7]]
    18. flatten展开的数组b:
    19. [0 1 2 3 4 5 6 7]
    20. ravel展开的数组c:
    21. [0 1 2 3 4 5 6 7]
    22. 修改b[1]后数组b:
    23. [ 0 10 2 3 4 5 6 7]
    24. 修改b[1]后数组a:
    25. [[0 1 2 3]
    26. [4 5 6 7]]
    27. 修改c[1]后数组b:
    28. [ 0 10 2 3 4 5 6 7]
    29. 修改c[1]后数组a:
    30. [[ 0 10 2 3]
    31. [ 4 5 6 7]]
    32. ‘’‘

    数组变换

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

    转置T

    numpy.transpose(axes)

    返回转置的数组。

    参数说明:

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

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

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

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

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

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

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

    滚动轴

    numpy.rollaxis(a, axis, start)

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

    参数说明:

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

    先看二维的情况:

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

    从效果来看就是转置。

    再看三维的情况:

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

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

    交换轴

    numpy.swapaxes(arr, axis1, axis2)

    交换数组的两个轴

    参数说明:

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

    从上例子可以看到,滚动轴和交换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。

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

    扩展数组的维度

    numpy.expand_dims(arr, axis)

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

    参数说明:

    • arr:输入数组
    • axis:新轴插入的位置
    1. x = np.array([[11,12],[21,22]])
    2. print('原始数组:\n', x)
    3. y = np.expand_dims(x, axis = 0)
    4. print('插入维度后的数组:\n', y)
    5. y = np.expand_dims(x, axis = 1)
    6. print('插入维度后的数组:\n', y)
    7. ‘’'
    8. 原始数组:
    9. [[11 12]
    10. [21 22]]
    11. 插入维度后的数组:
    12. [[[11 12]
    13. [21 22]]]
    14. 插入维度后的数组:
    15. [[[11 12]]
    16. [[21 22]]]
    17. ‘''

    删除单维度

    numpy.squeeze(arr, axis)

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

    参数说明:

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

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

    连接数组

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

    沿轴连接

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

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

    参数说明:

    • a1, a2, ...:相同形状的数组
    • axis:沿着它连接数组的轴,默认为 0
    1. import numpy as np
    2. a = np.array([[1,2],[3,4]])
    3. print ('第一个数组:')
    4. print (a)
    5. print ('\n')
    6. b = np.array([[5,6],[7,8]])
    7. print ('第二个数组:')
    8. print (b)
    9. print ('\n')
    10. # 两个数组的维度相同
    11. print ('沿轴 0 连接两个数组:')
    12. print (np.concatenate((a,b)))
    13. print ('\n')
    14. print ('沿轴 1 连接两个数组:')
    15. print (np.concatenate((a,b),axis = 1))
    16. ‘’’
    17. 第一个数组:
    18. [[1 2]
    19. [3 4]]
    20. 第二个数组:
    21. [[5 6]
    22. [7 8]]
    23. 沿轴 0 连接两个数组:
    24. [[1 2]
    25. [3 4]
    26. [5 6]
    27. [7 8]]
    28. 沿轴 1 连接两个数组:
    29. [[1 2 5 6]
    30. [3 4 7 8]]
    31. ’‘’
    numpy.stack(arrays, axis)

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

    参数说明:

    • arrays相同形状的数组序列
    • axis:返回数组中的轴,输入数组沿着它来堆叠
    1. import numpy as np
    2. a = np.array([[1,2],[3,4]])
    3. print ('第一个数组:')
    4. print (a)
    5. print ('\n')
    6. b = np.array([[5,6],[7,8]])
    7. print ('第二个数组:')
    8. print (b)
    9. print ('\n')
    10. print ('沿轴 0 堆叠两个数组:')
    11. print (np.stack((a,b),0))
    12. print ('\n')
    13. print ('沿轴 1 堆叠两个数组:')
    14. print (np.stack((a,b),1))
    15. ‘’’
    16. 第一个数组:
    17. [[1 2]
    18. [3 4]]
    19. 第二个数组:
    20. [[5 6]
    21. [7 8]]
    22. 沿轴 0 堆叠两个数组:
    23. [[[1 2]
    24. [3 4]]
    25. [[5 6]
    26. [7 8]]]
    27. 沿轴 1 堆叠两个数组:
    28. [[[1 2]
    29. [5 6]]
    30. [[3 4]
    31. [7 8]]]
    32. ’‘’

    水平堆叠

    numpy.hstack(arrays)

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

    1. import numpy as np
    2. a = np.array([[1,2],[3,4]])
    3. print ('第一个数组:')
    4. print (a)
    5. print ('\n')
    6. b = np.array([[5,6],[7,8]])
    7. print ('第二个数组:')
    8. print (b)
    9. print ('\n')
    10. print ('水平堆叠:')
    11. c = np.hstack((a,b))
    12. print (c)
    13. print ('\n’)
    14. ‘’’
    15. 第一个数组:
    16. [[1 2]
    17. [3 4]]
    18. 第二个数组:
    19. [[5 6]
    20. [7 8]]
    21. 水平堆叠:
    22. [[1 2 5 6]
    23. [3 4 7 8]]
    24. ‘''

    垂直堆叠

    numpy.vstack(arrays)

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

    1. import numpy as np
    2. a = np.array([[1,2],[3,4]])
    3. print ('第一个数组:')
    4. print (a)
    5. print ('\n')
    6. b = np.array([[5,6],[7,8]])
    7. print ('第二个数组:')
    8. print (b)
    9. print ('\n')
    10. print ('竖直堆叠:')
    11. c = np.vstack((a,b))
    12. print (c)
    13. ‘’'
    14. 第一个数组:
    15. [[1 2]
    16. [3 4]]
    17. 第二个数组:
    18. [[5 6]
    19. [7 8]]
    20. 竖直堆叠:
    21. [[1 2]
    22. [3 4]
    23. [5 6]
    24. [7 8]]
    25. ‘''

    分割数组

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

    沿轴分割

    numpy.split(ary, indices_or_sections, axis)

    参数说明:

    • ary:被分割的数组
    • indices_or_sections:如果是一个整数,就用该数平均切分,如果是一个数组,为沿轴切分的位置(左开右闭)
    • axis:设置沿着哪个方向进行切分,默认为 0,横向切分,即水平方向。为 1 时,纵向切分,即竖直方向。
    1. import numpy as np
    2. a = np.arange(9)
    3. print ('第一个数组:')
    4. print (a)
    5. print ('\n')
    6. print ('将数组分为三个大小相等的子数组:')
    7. b = np.split(a,3)
    8. print (b)
    9. print ('\n')
    10. print ('将数组在一维数组中表明的位置分割:')
    11. b = np.split(a,[4,7])
    12. print (b)
    13. ‘’’
    14. 第一个数组:
    15. [0 1 2 3 4 5 6 7 8]
    16. 将数组分为三个大小相等的子数组:
    17. [array([0, 1, 2]), array([3, 4, 5]), array([6, 7, 8])]
    18. 将数组在一维数组中表明的位置分割:
    19. [array([0, 1, 2, 3]), array([4, 5, 6]), array([7, 8])]
    20. ’‘’

    axis 为 0 时在水平方向分割,axis 为 1 时在垂直方向分割:

    1. import numpy as np
    2. a = np.arange(16).reshape(4, 4)
    3. print('第一个数组:')
    4. print(a)
    5. print('默认分割(0轴):')
    6. b1,b2 = np.split(a,2)
    7. print('数组1:\n', b1,'\n数组2:\n', b2)
    8. print('沿纵向分割:')
    9. c1,c2 = np.split(a,2,1)
    10. print('数组1:\n', c1,'\n数组2:\n', c2)
    11. ‘’’
    12. 第一个数组:
    13. [[ 0 1 2 3]
    14. [ 4 5 6 7]
    15. [ 8 9 10 11]
    16. [12 13 14 15]]
    17. 默认分割(0轴):
    18. 数组1:
    19. [[0 1 2 3]
    20. [4 5 6 7]]
    21. 数组2:
    22. [[ 8 9 10 11]
    23. [12 13 14 15]]
    24. 沿纵向分割:
    25. 数组1:
    26. [[ 0 1]
    27. [ 4 5]
    28. [ 8 9]
    29. [12 13]]
    30. 数组2:
    31. [[ 2 3]
    32. [ 6 7]
    33. [10 11]
    34. [14 15]]
    35. ''

    水平分割

    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时,数组是加在右边(行数要相同)。
    1. import numpy as np
    2. a = np.array([[1, 2, 3], [4, 5, 6]])
    3. print('第一个数组:\n', a)
    4. print('向数组添加元素:')
    5. print(np.append(a, [7, 8, 9]))
    6. print('沿轴 0 添加元素:')
    7. print(np.append(a, [[7, 8, 9]], axis=0))
    8. print('沿轴 1 添加元素:')
    9. print(np.append(a, [[10, 11, 12], [21, 22, 23]], axis=1))
    10. ‘’’
    11. 第一个数组:
    12. [[1 2 3]
    13. [4 5 6]]
    14. 向数组添加元素:
    15. [1 2 3 4 5 6 7 8 9]
    16. 沿轴 0 添加元素:
    17. [[1 2 3]
    18. [4 5 6]
    19. [7 8 9]]
    20. 沿轴 1 添加元素:
    21. [[ 1 2 3 10 11 12]
    22. [ 4 5 6 21 22 23]]
    23. ’‘’

    按索引插入值

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

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

    参数说明:

    • arr:输入数组
    • obj:在其之前插入值的索引
    • values:要插入的值
    • axis:沿着它插入的轴,如果未提供,则输入数组会被展开;传递了 Axis 参数。 会广播值数组来配输入数组。
    1. import numpy as np
    2. a = np.arange(12).reshape(3,4)
    3. print('第一个数组:\n', a)
    4. print('未传递 Axis 参数。 在3前插入[100, 200]之前输入数组会被展开。')
    5. print(np.insert(a, 3, [100, 200]))
    6. #传递了 Axis 参数。 会广播值数组来配输入数组
    7. print('指定0轴的2行(0行开始)前插入[100,101,102,103]:')
    8. print(np.insert(a, 2, [100,101,102,103], axis=0))
    9. print('指定0轴的2行(0行开始)前插入[100],按广播扩展:')
    10. print(np.insert(a, 2, [100], axis=0))
    11. print('指定1轴的3列前插入[100,101,102](会自动转置):')
    12. print(np.insert(a, 3, [100,101,102], axis=1))
    13. print('指定1轴的3列前插入[100],按广播扩展:')
    14. print(np.insert(a, 3, 100, axis=1))
    15. ‘’’
    16. 第一个数组:
    17. [[ 0 1 2 3]
    18. [ 4 5 6 7]
    19. [ 8 9 10 11]]
    20. 未传递 Axis 参数。 在3前插入[100, 200]之前输入数组会被展开。
    21. [ 0 1 2 100 200 3 4 5 6 7 8 9 10 11]
    22. 指定0轴的2行(0行开始)前插入[100,101,102,103]:
    23. [[ 0 1 2 3]
    24. [ 4 5 6 7]
    25. [100 101 102 103]
    26. [ 8 9 10 11]]
    27. 指定0轴的2行(0行开始)前插入[100],按广播扩展:
    28. [[ 0 1 2 3]
    29. [ 4 5 6 7]
    30. [100 100 100 100]
    31. [ 8 9 10 11]]
    32. 指定1轴的3列前插入[100,101,102](会自动转置):
    33. [[ 0 1 2 100 3]
    34. [ 4 5 6 101 7]
    35. [ 8 9 10 102 11]]
    36. 指定1轴的3列前插入[100],按广播扩展:
    37. [[ 0 1 2 100 3]
    38. [ 4 5 6 100 7]
    39. [ 8 9 10 100 11]]
    40. ’‘’

    删除指定子数组

    Numpy.delete(arr, obj, axis)

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

    参数说明:

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

    数组去重

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

    返回见下面的说明

    参数说明:

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

  • 相关阅读:
    固定翼飞机姿态角Backstepping反步法控制
    【Spring】Day16
    CSAPP Bomb Lab
    D365 根据选中数据行的字段值,控制按钮是否可点击
    物企大变局时代,SRM供应商采购系统助力企业打造物业采购数字化标杆
    PreparedStatement vs Statement 不同及其使用
    Redis学习(三)之 分布式锁详解
    POST注入 | 盲注 | 宽字节注入
    java开发
    多元高斯分布
  • 原文地址:https://blog.csdn.net/spiritx/article/details/133520793