numpy 官网文章翻译

官网地址
什么是 numpy numpy 是 Python 的一个科学计算包。提供了多种array对象、衍生对象(masked arrays 和 matrices)、及其对其日常快速操作,包括数学、逻辑、形状操作、分类、选择、I/O、离散傅里叶(discrete Fourier transforms)、基本线性代数、基本数据操作、随机墨迹等。
numpy 包的核心是ndarray,他分装了n-维 array 对象(每个维度的数据类型一致),这使得各种操作都在编译好的代码中执行,从而提高了性能。
NumPyarray对象 与 Python 标准序列区别:

  • NumPy 对象在创建时有一个固定的大小,而 Python 的 list 没有。改变 ndarray 的大小会删除原来对象,创建一个新的对象
  • NumPy所有数据类型是一致的,这样在内存中占用的大小才是一致的。例外:可以有对象数组(Python,包括 NumPy),允许不同大小元素的数组。
  • NumPy 对象更容易对于大量数据进行高级数学和其他类型操作。相较于 Python 内置序列,NumPy 操作执行效率更高,代码更少。
  • 越来越多的科学和数学 Python 包会使用 NumPy 包,尽管它们支持 Python 内置序列,但在操作之前都会转换成 NumPy 对象。换言之,要想有效的使用现在的科学\数学 Python 包,只了解 Python 内置序列是不够的,我们也要了解 NumPy 对象的使用。
科学计算的关键就是序列大小和速度。举个简单例子,在一个一维的序列中,每个元素要与另一个长度相同的序列相应的元素做乘积,我们可以迭代每个元素。
c = [] for i in range(len(a)): c.append(a[i]*b[i])

这个过程会输出正确答案,但如果列表 a 和 b 每个元素都是几百万,那我们就会为 Python 低效的循环付出代价。c 语言可以更快的完成相同任务(我们假设不去做变量声明、初始化和内存分配):
for(i = 0; i < rows; i++):{ c[i] = a[i]*b[i] }

这解决了解释Python代码和操作Python对象所涉及的所有开销,但牺牲了Python编码的好处。此外,随着数据维度增加,工作量也增加,如在 2 维数组中,c 语言编码为
for (i = 0; i < rows; i++): { for (j = 0; j < columns; j++): { c[i][j] = a[i][j]*b[i][j]; } }

而 NumPy 为这两张方案这个为我们提供了最优解:当涉及到 ndarray 时,逐个元素操作是默认模式,而实际上是由 提前变异的C语言快速执行。NumPy 代码运行速度与 C 语言接近,同时基于 Python 代码也很简洁(比 Python 还简介简洁!)。最后一个例子说明了 NumPy 的两个优势:矢量化(vectorization)和广播(broadcasting)。
c = a*b
矢量化
矢量化意味着代码中没有肉眼可见的循环和索引,而他们其实发生了,只不过优化后“秘密的进行着”——由预编译的 C 语言运行。
矢量化优点
  • 矢量化代码更简洁易读
  • 代码越少,bug 越少
  • 代码更类似于标准的数学符号(这样修改代码的数学结构会更容易)
  • 向量化会有更多“Pythonic”代码,没有矢量化,代码就会充斥着低效和难以读取的循环。
广播
广播是一个术语,用于描述操作的隐式逐个元素的行为。通常说来,在 NumPy中,包括算数、逻辑、按位、函数等所有操作,以这种隐式逐个元素的方式进行——即广播。此外,上述举例中,a 和 b 可以是形状相同的多维数组、标量、数组,甚至可以是不同形状的两个数组(前提是较小的数组扩大成较大数组的形状)。更多信息请见 broadcasting。
NumPy 的 ndarray 全面支持面向对象。例如,ndarray是一个类,具有多种方法和对象。其中,许多方法都被NumPy最外层命名空间函数反映,允许程序员在他们喜欢的任何范式中编写代码。这种灵活性使得 NumPy 数组和 NumPyndarray 成为了Python 中多位数据交互的实际语言。
安装 安装 NumPy 唯一需要的条件就是 Python。如果你不懂 Python,只想用最简单的方式的话,我们推荐anaconda,它包括了 Python、NumPy 和许多其他常见科学计算和数据分析的Python 包。
Linux 和 macOS 安装 NumPy 可以使用pipconda,或者使用下载源。更多信息请参考https://numpy.org/install/#py...。

  • donda
    你可以从defaults或者conda-forge 安装 numpy。
Best practice, use an environment rather than install in the base env conda create -n my-env conda activate my-env # If you want to install from conda-forge conda config --env --add channels conda-forge # The actual install command conda install numpy

  • pip
    pip install numpy
NumPy 快速启动 使用 NumPy 前需要先了解Python;需要安装matplotlib
学习目标
  • 了解一维、二维和 n 维数组的区别
  • 了解在不使用 for 循环的情况下如何将一些线性代数应用到 n 维数组中
  • 了解 n 维数组的轴和形状特性
[基础知识]
NumPy 的主要对象为均匀的多维数组。数组是元素表(通产为数字),所有元素的类型一致,由一个非负整数的元组进行索引。在 NumPy 中,维度称为轴(axes)。
例如,在一个3 维空间中,一个点的坐标数组为[1, 2, 1],它只有一个轴,轴含有 3 个元素,因此我们可以说其长度为 3。下面的例子中的数组中有 2 个轴,第一个轴的长度为 2,第二个长度为 3.
[[1., 0., 0.], [0., 1., 2.]]

NumPy 的数组类称为ndarray,别名为array。记住:numpy.array与 Python 标准库的类array.array不同,后者只能解决以为数组,且功能较少。
ndarray最重要的参数:
  1. ndarray.ndim :数组维度的数量
  2. ndarray.shape: 数组的维度,返回一个标明每个维度的数组的大小的元组,如一个 n 行 m 列的矩阵,其 shape 为(n,m),元组的长度就是ndim值。
  3. ndarray.size:数组所有元素的个数,等于 shape 所有值的乘积
  4. ndarray.dtype:数组中元素的数据类型,我们可以创建或者指定为标准 Python 数据类型,也可以使用 NumPy 提供的类型,如numpy.int32、numpy.int16、numpy.float64等
  5. ndarray.itemsize:数组中每个元素的 字节大小,例如float64的大小为 8(64/8),float64为 4 字节。等同于ndarray.dtype.itemsize.
  6. ndarray.data:
创建数组
  • 将列表或者元组转换为数组
import numpy as np a = np.array([2, 3, 4]) a #array([2, 3, 4]) a.dtype #dtype('int64') b = np.array([1.2, 3.5, 5.1]) b.dtype #dtype('float64')

【numpy 官网文章翻译】有一种常见的错误就是放入太多了参数,而要求是放入一个为序列的参数
a = np.array(1, 2, 3, 4)# WRONG Traceback (most recent call last): ... TypeError: array() takes from 1 to 2 positional arguments but 4 were given a = np.array([1, 2, 3, 4])# RIGHT

array 方法 将含有一层序列的序列转换成二维数组,将含有两层序列的序列转换成三维数组,以此类推。
b = np.array([(1.5, 2, 3), (4, 5, 6)]) b array([[1.5, 2. , 3. ], [4. , 5. , 6. ]]) b.shape #(2,3)

创建数组时可以指定数据类型
c = np.array([[1, 2], [3, 4]], dtype=complex) c array([[1.+0.j, 2.+0.j], [3.+0.j, 4.+0.j]])

  • 通过原始占位符创建数组
    通常来说,数组元素的类型未知,但其大小一直。因此,NumPy 也可以通过原始占位符的方法创建数组,这种方法减少了扩充数组这种高成本操作的的需要。
  • zero、ones、empty
    zero函数可以创建一个全是0 的数组,
    ones函数可以创建全是 1 的数组,
    empty函数可以根据缓存创建一个随机内容的数组。
    这三种方法数据类型默认为float64,但可以通过关键字参数dtype进行修改。
np.zeros((3, 4)) array([[0., 0., 0., 0.], [0., 0., 0., 0.], [0., 0., 0., 0.]]) np.ones((2, 3, 4), dtype=np.int16) array([[[1, 1, 1, 1], [1, 1, 1, 1], [1, 1, 1, 1]],[[1, 1, 1, 1], [1, 1, 1, 1], [1, 1, 1, 1]]], dtype=int16) np.empty((2, 3)) array([[3.73603959e-262, 6.02658058e-154, 6.55490914e-260],# may vary [5.30498948e-313, 3.14673309e-307, 1.00000000e+000]])

  • 创建数字序列
    arange函数可以创建一个类似与range的序列,但返回数组。
np.arange(10, 30, 5) #头、尾、步长 array([10, 15, 20, 25]) np.arange(0, 2, 0.3)# it accepts float arguments array([0. , 0.3, 0.6, 0.9, 1.2, 1.5, 1.8])

  • linspace
    当浮点数作为arange的参数时,由于精度问题,通常很难预测每个元素的值,因此最好使用linspace函数,这个函数可以接收元素个数作为一个参数。
from numpy import pi np.linspace(0, 2, 9) array([0., 0.25, 0.5 , 0.75, 1., 1.25, 1.5 , 1.75, 2.]) x = np.linspace(0, 2 * pi, 100) f = np.sin(x)

  • 其他
array|zeros|zeros_like|ones|ones_like|empty|empty_like
等等等等
打印数组
NumPy 数组结构形似嵌套列表,但具有一些特征
  • 最后的轴从左向右打印
  • 倒数第二从上到下打印
  • 其余从上到下打印,每个切片与下一个切片各一个空行
  • 如果矩阵太大的话,会自动跳过总监部分,只显示四周,若要全部显示,我们可以设置set_printoptions
c = np.arange(24).reshape(2, 3, 4)# 3d array print(c) [[[ 0123] [ 4567] [ 89 10 11]] [[12 13 14 15] [16 17 18 19] [20 21 22 23]]]np.set_printoptions(threshold=sys.maxsize)# sys module should be imported

基本操作
  1. 算术操作应用于元素身上,结果返回一个新的答案数组。
a = np.array([20, 30, 40, 50]) b = np.arange(4) b #array([0, 1, 2, 3]) c = a - b c #array([20, 29, 38, 47]) b**2 #array([0, 1, 4, 9]) 10 * np.sin(a) #array([ 9.12945251, -9.88031624,7.4511316 , -2.62374854]) a < 35 array([ True,True, False, False])

  1. *求乘积操作是针对于每个元素,如果要减小矩阵操作,使用@或者dot函数。
A = np.array([[1, 1], [0, 1]]) B = np.array([[2, 0], [3, 4]]) A * B# elementwise product array([[2, 0], [0, 4]]) A @ B# matrix product array([[5, 4], [3, 4]]) A.dot(B)# another matrix product array([[5, 4], [3, 4]])

  1. +=*=操作是对元数组的操作,不会返回一个新的数组。
    rg = np.random.default_rng(1)# create instance of default random number generator a = np.ones((2, 3), dtype=int) b = rg.random((2, 3)) a *= 3 a array([[3, 3, 3], [3, 3, 3]]) b += a b array([[3.51182162, 3.9504637 , 3.14415961], [3.94864945, 3.31183145, 3.42332645]]) a += b# b is not automatically converted to integer type Traceback (most recent call last): ... numpy.core._exceptions._UFuncOutputCastingError: Cannot cast ufunc 'add' output from dtype('float64') to dtype('int64') with casting rule 'same_kind'

  2. 当操作的数组们的数据类型不同,数组结果与更加综合精确的一致(upcasting)
    a = np.ones(3, dtype=np.int32) b = np.linspace(0, pi, 3) b.dtype.name 'float64' c = a + b c array([1., 2.57079633, 4.14159265]) c.dtype.name 'float64' d = np.exp(c * 1j) d array([ 0.54030231+0.84147098j, -0.84147098+0.54030231j, -0.54030231-0.84147098j]) d.dtype.name 'complex128'

  3. 许多一元操作,如求所有元素的和,在ndarray类的方法中。
    a = rg.random((2, 3)) a array([[0.82770259, 0.40919914, 0.54959369], [0.02755911, 0.75351311, 0.53814331]]) a.sum() 3.1057109529998157 a.min() 0.027559113243068367 a.max() 0.8277025938204418

  4. 在默认情况下,对数组的操作可以不管其形状,看做列表即可。但在特殊情况下,可以指定axis参数,沿着这个轴进行操作。
    b = np.arange(12).reshape(3, 4) b array([[ 0,1,2,3], [ 4,5,6,7], [ 8,9, 10, 11]]) >>> b.sum(axis=0)# sum of each column array([12, 15, 18, 21]) >>> b.min(axis=1)# min of each row array([0, 4, 8]) >>> b.cumsum(axis=1)# cumulative sum along each row array([[ 0,1,3,6], [ 4,9, 15, 22], [ 8, 17, 27, 38]])

    推荐阅读