Numpy 基础笔记

本贴最后更新于 1282 天前,其中的信息可能已经斗转星移

numpy 概述

  1. Numerical Python,数值的 Python,补充了 Python 语言所欠缺的数值计算能力。
  2. Numpy 是其数据分析及机器学习库的底层库。
  3. Numpy 完全标准 C 语言实现,运行效率充分优化。
  4. Numpy 开源免费。

numpy 历史

  1. 1995 年,Numeric,Python 语言数值计算扩充。
  2. 2001 年,Scipy -> Numarray,多维数组运算。
  3. 2005 年,Numeric + Numarray -> Numpy。
  4. 2006 年,Numpy 脱离 Scipy 成为独立项目。

numpy 的核心:多维数组

  1. 代码简洁:减少 Python 代码中的循环。
  2. 底层实现:厚内核(C ) + 薄接口(Python),保证性能。

numpy 基础

ndarray 数组

np.ndarray 类的对象表示 n 维数组:

import numpy as np arr = np.array([1, 2, 3, 4, 5, 6]) print(arr, type(arr)) print(arr.shape) # 数组的维度 arr.shape = (2, 3) # 修改数组的维度为 2 行 3 列 print(arr, arr.shape) arr.shape = (6,) # 数组的运算 print(arr) print("arr * 3: ", arr * 3) print("arr + 3: ", arr + 3) print("arr > 3: ", arr > 3) print("arr + arr: ", arr + arr) """ [1 2 3 4 5 6] <class 'numpy.ndarray'> (6,) [[1 2 3] [4 5 6]] (2, 3) [1 2 3 4 5 6] arr * 3: [ 3 6 9 12 15 18] arr + 3: [4 5 6 7 8 9] arr > 3: [False False False True True True] arr + arr: [ 2 4 6 8 10 12] """

内存中的 ndarray 对象

元数组(metadata)

存储对目标数组的描述信息,如:dim countshapesizedtypedata 等。

实际数据

完整的数组数据

将实际数据与元数据分开存放,一方面提高了内存空间的使用效率,另一方面减少对实际数据的访问频率,提高性能。

ndarray 数组对象的特点

  1. Numpy 数组是同质数组,即所有元素的数据类型必须相同。
  2. Numpy 数组的下标从 0 开始,最后一个元素的下标为数组长度减 1

ndarray 数组对象的创建

  • np.array(任何可被解释为 Numpy 数组的逻辑结构):
    import numpy as np a = np.array([1, 2, 3, 4, 5, 6]) print(a) """ [1 2 3 4 5 6] """
  • np.arange(起始值(0),终止值,步长(1))
    import numpy as np a = np.arange(0, 5, 1) print(a) b = np.arange(0, 10, 2) print(b) """ [0 1 2 3 4] [0 2 4 6 8] """
  • np.zeros(数组元素个数,dtype='类型')
    import numpy as np a = np.zeros(10) print(a) """ [0. 0. 0. 0. 0. 0. 0. 0. 0. 0.] """
  • np.ones(数组元素个数,dtype='类型')
    import numpy as np a = np.ones(10) print(a) """ [1. 1. 1. 1. 1. 1. 1. 1. 1. 1.] """

ndarray 对象属性的基本操作

数组的维度:np.ndarray.shape

import numpy as np arr = np.array([1, 2, 3, 4, 5, 6]) print(type(arr), arr, arr.shape) arr = np.array([ [1, 2, 3], [4, 5, 6], [7, 8, 9]]) print(type(arr), arr, arr.shape) """ <class 'numpy.ndarray'> [1 2 3 4 5 6] (6,) <class 'numpy.ndarray'> [[1 2 3] [4 5 6] [7 8 9]] (3, 3) """

元素的数据类型:np.ndarray.dtype

import numpy as np a = np.array([1, 2, 3, 4, 5, 6]) print(type(a), a, a.dtype) b = a.astype(float) # 转换 a 的类型为 float print(type(b), b, b.dtype) c = a.astype(str) # 转换 a 的类型为 str print(type(c), c, c.dtype) """ <class 'numpy.ndarray'> [1 2 3 4 5 6] int32 <class 'numpy.ndarray'> [1. 2. 3. 4. 5. 6.] float64 <class 'numpy.ndarray'> ['1' '2' '3' '4' '5' '6'] <U11 """

数组元素的个数:np.ndarray.size

import numpy as np a = np.array([ [1, 2, 3], [4, 5, 6], [7, 8, 9]]) print(a.shape, a.size, len(a)) """ (3, 3) 9 3 """

数组元素索引(下标)

数组对象[..., 页号, 行号, 列号]

下标从 0 开始,到数组 len - 1 结束

import numpy as np a = np.array([ [[1, 2], [3, 4]], [[5, 6], [7, 8]] ]) print(a, a.shape) print(a[0]) print(a[0][0]) print(a[0][1][0]) print(a[0, 1, 0]) """ [[[1 2] [3 4]] [[5 6] [7 8]]] (2, 2, 2) [[1 2] [3 4]] [1 2] 1 3 """

ndarray 对象属性操作详解

Numpy 内部基本数据类型

类型名 类型表示符
布尔型 bool_
有符号整数型 int8(-128~127)/int16/int32/int64
无符号整数型 uint8(0~255)/uint16/uint32/uint64
浮点型 float16/float32/float64
复数型 complex64/complex128
字符串型 str_,每个字符用 32 位 Unicode 编码表示

自定义复合类型

import numpy as np data = [ ('zs', [90, 80, 85], 14), ('ls', [92, 81, 83], 15), ('ww', [95, 85, 95], 16), ] # 第一种设置 dtype 的方式 a = np.array(data, dtype='U2, 3int32, int32') print(a) print(a[0]['f0'], ':', a[1]['f1'], a[1]['f2']) # 第二种设置的 dtype 的方式 b = np.array(data, dtype=[ ('name', 'str', 2), ('scores', 'int32', 3), ('age', 'int32', 1), ]) print(b, b[2]['age']) # 第三种设置的 dtype 的方式 c = np.array(data, dtype={ 'names': ['name', 'scores', 'age'], 'formats': ['U2', '3int32', 'int32'], }) print(c) print(c[1]['name']) """ [('zs', [90, 80, 85], 14) ('ls', [92, 81, 83], 15) ('ww', [95, 85, 95], 16)] [('zs', [90, 80, 85], 14) ('ls', [92, 81, 83], 15) ('ww', [95, 85, 95], 16)] 16 [('zs', [90, 80, 85], 14) ('ls', [92, 81, 83], 15) ('ww', [95, 85, 95], 16)] ls """

类型字符码

类型 字符码
np.bool_ ?
np.int8/16/32/64 i1/i2/i4/i8
np.uint8/16/32/64 u1/u2/u4/u8
np.float/16/32/64 f2/f4/f8
np.complex64/128 c8/c16
np.str_ U<字符数>
np.datetime64 M8[Y] M8[M] M8[D] M8[H] M8[m] M8[s]

字节序前缀

一般用于多字节整数和字符串:

</>/[=]分别表示小端/大端/硬件字节序

类型字符码格式

< 字节序前缀 >< 维度 >< 类型 >< 字节数或字符数 >

  • 3i4:大端字节序,3 个元素的一维数组,每个元素都是整型,每个整型元素占 4 个字节。
  • <(2,3)u8:小端字节序,6 个元素 2 行 3 列的二维数组,每个元素都是无符号整型,每个无符号整型元素占 8 个字节。
  • U7:包含 7 个字符的 Unicode 字符串,每个字符占 4 个字节,采用默认字节序。

ndarray 数组对象维度的操作

视图变维(数据共享)

改变原数组会影响新数组,即数组之间的数据相互共享。

reshape()ravel()

import numpy as np a = np.arange(1, 9) print(a) b = a.reshape(2, 4) # 视图变维:变为 2 行 4 列的二维数组 print(b) c = b.reshape(2, 2, 2) # 视图变维:变维 2 页 2 行 2 列的三维数组 print(c) d = c.ravel() # 视图变维:变为 1 维数组 a[0]=99 print(d) """ [1 2 3 4 5 6 7 8] [[1 2 3 4] [5 6 7 8]] [[[1 2] [3 4]] [[5 6] [7 8]]] [99 2 3 4 5 6 7 8] """

复制变维(数据独立)

改变原数组不会影响新数组,即数组之间的数据相互独立。

import numpy as np a = np.arange(1, 9) b = a.reshape(2, 2, 2) c = b.flatten() print(c) b[0][0][0] = 99 print(c) """ [1 2 3 4 5 6 7 8] [1 2 3 4 5 6 7 8] """

ndarray 数组切片操作

一维数组

一维数组切片的语法为 [起始下标:结束下标:步长],表示从起始下标开始,以指定的步长切割数组,到结束下标为止,但不包括结束下标的元素。

注意

  • 起始下标,结束下标和步长可以省略,起始下标默认为 0,结束下标默认为 数组长度,步长默认为 1
  • 起始下标和结束下标可以为负数-1 对应列表最后一个元素,-2 表示倒数第二个,依次类推。步长可以为 -1-1 表示倒序对数组进行切片。

例如 a[3:6:1] 表示对数组 a 从下标 3 开始,到下标 6 结束(不包括 6),步长为 1 进行切片,所得元素下标分别为 3,4,5

下面是一个综合例子:

import numpy as np a = np.arange(1, 10) print(a) # [1 2 3 4 5 6 7 8 9] print(a[:3]) # [1 2 3] print(a[3:6]) # [4 5 6] print(a[6:]) # [7 8 9] print(a[::-1]) # [9 8 7 6 5 4 3 2 1] print(a[-1:-4:-1]) # [9 8 7] print(a[-4:-7:-1]) # [6 5 4] print(a[-7::-1]) # [3 2 1] print(a[::]) # [1 2 3 4 5 6 7 8 9] print(a[:]) # [1 2 3 4 5 6 7 8 9] print(a[::3]) # [1 4 7] print(a[1::3]) # [2 5 8] print(a[2::3]) # [3 6 9]

二维数组

二维数组切片是一维数组切片的扩展,是类似的。语法为 [起始下标:结束下标:步长, 起始下标:结束下标:步长],逗号前表示对行元素进行切片,逗号后表示对列元素进行切片。

例如 a[:2, :2] 表示对二维数组进行切片,行下标从 0 开始,到下标 2 为止(不包括 2),步长默认为 1;列下标从 0 开始,到下标 2 为止(不包括 2),步长默认为 1

下面是一个综合例子:

import numpy as np a = np.arange(1, 10) a.resize(3, 3) print(a) print(a[:2, :2]) print(a[::2, ::2]) """ [[1 2 3] [4 5 6] [7 8 9]] [[1 2] [4 5]] [[1 3] [7 9]] """

ndarray 掩码操作

基于 bool 数组的掩码

import numpy as np a = np.arange(100) # 输出 3 的倍数 print(a[a % 3 == 0]) """ [ 0 3 6 9 12 15 18 21 24 27 30 33 36 39 42 45 48 51 54 57 60 63 66 69 72 75 78 81 84 87 90 93 96 99] """

基于索引的掩码

import numpy as np # 基于索引的掩码 names = np.array(['Apple', ' Huawei', 'Mi', 'Oppo', 'vivo']) rank = [1, 0, 3, 4, 2] print(names[rank]) """ [' Huawei' 'Apple' 'Oppo' 'vivo' 'Mi'] """

多维数组的组合与拆分

水平方向上的组合与拆分

hstack 函数实现数组水平方向上的组合,hsplit 函数实现数组水平方向上的拆分。

import numpy as np a = np.arange(1, 7).reshape(2, 3) b = np.arange(7, 13).reshape(2, 3) # 水平方向完成组合操作,生成新数组 c = np.hstack((a, b)) # 水平方向完成拆分操作,生成两个数组 d, e = np.hsplit(c, 2) print(c) print(d) print(e) """ [[ 1 2 3 7 8 9] [ 4 5 6 10 11 12]] [[1 2 3] [4 5 6]] [[ 7 8 9] [10 11 12]] """

垂直方向上的组合与拆分

vstack 函数实现数组垂直方向上的组合,vsplit 函数实现数组垂直方向上的拆分。

import numpy as np a = np.arange(1, 7).reshape(2, 3) b = np.arange(7, 13).reshape(2, 3) # 垂直方向完成组合操作,生成新数组 c = np.vstack((a, b)) # 垂直方向完成拆分操作,生成两个数组 d, e = np.vsplit(c, 2) print(c) print(d) print(e) """ [[ 1 2 3] [ 4 5 6] [ 7 8 9] [10 11 12]] [[1 2 3] [4 5 6]] [[ 7 8 9] [10 11 12]] """

深度方向上的组合与拆分

dstack 函数实现数组深度方向上的组合,dsplit 函数实现数组深度方向上的拆分。

import numpy as np a = np.arange(1, 7).reshape(2, 3) b = np.arange(7, 13).reshape(2, 3) # 深度方向完成组合操作,生成新数组 c = np.dstack((a, b)) # 深度方向完成拆分操作,生成两个数组 d, e = np.dsplit(c, 2) print(c) print(d) print(e) """ [[[ 1 7] [ 2 8] [ 3 9]] [[ 4 10] [ 5 11] [ 6 12]]] [[[1] [2] [3]] [[4] [5] [6]]] [[[ 7] [ 8] [ 9]] [[10] [11] [12]]] """

多维数组组合与拆分的相关函数

通过 axis 作为关键字参数指定组合方向,取值如下:

  • 若待组合的数组都是二维数组:
    • 0 :垂直方向组合
    • 1:水平方向组合
  • 若待组合的数组都是三维数组:
    • 0:垂直方向组合
    • 1:水平方向组合
    • 2:深度方向组合

concatenate 函数可以实现数组的组合,split 函数可以实现数组的拆分。

import numpy as np a = np.arange(1, 7).reshape(2, 3) b = np.arange(7, 13).reshape(2, 3) c = np.concatenate((a, b), axis=0) d, e = np.split(c, 2, axis=0) print('a:', a) print('b:', b) print('c:', c) """ a: [[1 2 3] [4 5 6]] b: [[ 7 8 9] [10 11 12]] c: [[ 1 2 3] [ 4 5 6] [ 7 8 9] [10 11 12]] """

ndarray 的其他属性

  • shape:维度
  • dtype:元素类型
  • size:元素数量
  • ndim:维数,len(shape)
  • itemsize:元素字节数
  • nbytes:总字节数 = size x itemsize
  • real:复数数组的实部数组
  • imag:复数数组的虚部数组
  • T:数组对象的转置视图
  • flat:扁平迭代器
import numpy as np a = np.array([ [1+1j, 2+4j, 3+7j], [4+2j, 5+5j, 6+8j], [7+3j, 8+6j, 9+9j] ]) print(a.shape) print(a.dtype) print(a.ndim) print(a.size) print(a.itemsize) print(a.nbytes) print(a.real) print(a.imag) print(a.T) print(a.flat) """ (3, 3) complex128 2 9 16 144 [[1. 2. 3.] [4. 5. 6.] [7. 8. 9.]] [[1. 4. 7.] [2. 5. 8.] [3. 6. 9.]] [[1.+1.j 4.+2.j 7.+3.j] [2.+4.j 5.+5.j 8.+6.j] [3.+7.j 6.+8.j 9.+9.j]] <numpy.flatiter object at 0x55eaebdf7380> """
  • Python

    Python 是一种面向对象、直译式电脑编程语言,具有近二十年的发展历史,成熟且稳定。它包含了一组完善而且容易理解的标准库,能够轻松完成很多常见的任务。它的语法简捷和清晰,尽量使用无异义的英语单词,与其它大多数程序设计语言使用大括号不一样,它使用缩进来定义语句块。

    556 引用 • 674 回帖
  • numpy
    9 引用 • 1 关注
1 操作
zyk 在 2021-09-20 16:20:11 更新了该帖

相关帖子

欢迎来到这里!

我们正在构建一个小众社区,大家在这里相互信任,以平等 • 自由 • 奔放的价值观进行分享交流。最终,希望大家能够找到与自己志同道合的伙伴,共同成长。

注册 关于
请输入回帖内容 ...