关于numpy:numpy-官网文章翻译

5次阅读

共计 6286 个字符,预计需要花费 16 分钟才能阅读完成。

官网地址

什么是 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')

有一种常见的谬误就是放入太多了参数,而要求是放入一个为序列的参数

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)
[[[0  1  2  3]
  [4  5  6  7]
  [8  9 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]])
正文完
 0