Numpy 30 分钟快速上手

2020/2/2 NumPy

NumPy 是 Python 中科学计算的基本软件包。 本文是入门文档的机器翻译人工矫正的中译版。

# 简介

# NumPy 是什么

它是一个 Python 库,提供多维数组对象,各种派生对象(例如蒙版数组和矩阵)以及用于对数组进行快速操作的各种例程,包括数学,逻辑,形状处理,排序,选择,I/O(Input/Output),离散傅立叶变换,基本线性代数,基本统计运算,随机模拟等等。

NumPy 包的核心是* ndarray *对象。这封装了同类数据类型的 n 维数组,许多操作都在编译后的代码中执行以提高性能。NumPy 数组和标准 Python 序列之间有几个重要区别:

  • NumPy 数组在创建时具有固定的大小,这与 Python 列表(可以动态增长)不同。更改* ndarray *的大小将创建一个新数组并删除原始数组。
  • NumPy 数组中的所有元素都必须具有相同的数据类型,因此在内存中的大小将相同。例外:一个对象可以具有(Python,包括 NumPy)对象数组,从而允许数组具有不同大小的元素。
  • NumPy 数组有助于对大量数据进行高级数学运算和其他类型的运算。特别的,与使用 Python 的内置序列相比,执行此类操作的效率更高,代码更少。
  • 越来越多的基于 Python 的科学和数学软件包都在使用 NumPy 数组。尽管这些通常支持输入 Python 序列,但它们会在处理之前将此类输入转换为 NumPy 数组,并且通常会输出 NumPy 数组。换句话说,为了有效地使用许多(也许甚至是大多数)基于科学/数学的 Python 的现代软件,仅仅知道如何使用 Python 的内置序列类型是不够的-人们还需要知道如何使用 NumPy 数组。

关于序列大小和速度的要点在科学计算中特别重要。举一个简单的例子,考虑将一维序列中的每个元素与相同长度的另一序列中的对应元素相乘的情况。如果数据存储在两个 Python 列表ab中,我们可以遍历每个元素:

c = []
for i in range(len(a)):
    c.append(a[i]*b[i])
1
2
3

这会产生正确的答案,但是如果ab都包含数百万个数字,我们将为 Python 循环效率低下付出代价。我们可以通过编写 C 语言来更快地完成相同的任务(为清楚起见,我们忽略了变量声明和初始化,内存分配等)。

for (i = 0; i < rows; i++): {
  c[i] = a[i]*b[i];
}
1
2
3

这样可以节省解释 Python 代码和处理 Python 对象所涉及的所有开销,但会以使 Python 编码的优势成为代价。此外,所需的编码工作随着我们数据的维度增加而增加。例如,对于二维数组,C 代码(如前所述)扩展为

for (i = 0; i < rows; i++): {
  for (j = 0; j < columns; j++): {
    c[i][j] = a[i][j]*b[i][j];
  }
}
1
2
3
4
5

NumPy 为我们提供了两全其美的优势:当涉及到* ndarray *时,逐元素操作是“默认模式”,但是逐元素操作由预编译的 C 代码快速执行。在 NumPy 中

c = a * b
1

以接近 C 的速度完成了此前示例的工作,也有我们所期望的基于 Python 代码实现的简洁。的确,NumPy 语法甚至更简洁!最后一个示例说明了 NumPy 的两项功能,这是其强大功能的基础:矢量化和广播。

# NumPy 为何快速

向量化描述代码中没有任何的显式循环,索引等操作-当然,这些事情只是“在幕后”发生,发生在优化过的预编译 C 代码中的。向量化代码具有许多优点,其中包括:

  • 向量化的代码更简洁,更易于阅读
  • 更少的代码量通常意味着更少的错误
  • 该代码更类似于标准数学符号(通常更容易正确地对数学构念进行编码)
  • 向量化产生更多的“pyhton 化”代码。没有向量化,我们的代码将效率低下,并且难以阅读for循环。

广播是一个术语,用于描述操作的隐式逐元素行为;一般而言,在 NumPy 中,所有运算,不仅是算术运算,更包括逻辑,位,函数等,都以这种逐个元素的隐式方式运行,即广播。此外,在上面的示例中,ab可以是相同形状的多维数组,也可以是标量和数组,甚至可以是形状不同的两个数组,条件是较小的数组可以“扩展”到较大的形状 以这样的方式使得结果广播是明确的。 有关广播的详细“规则”,请参阅 numpy.doc.broadcasting (opens new window)

# 还有谁使用 NumPy

NumPy 完全支持面向对象的方法,再次从* ndarray *开始。例如,*ndarray *是一个类,具有许多方法和属性。它的许多方法都被最外层的 NumPy 命名空间中的函数镜像,从而允许程序员以他们喜欢的任何范式进行编码。这种灵活性使 NumPy 数组语言和 NumPy *ndarray *类成为了 Python 中使用的多维数据交换的事实上的语言。

# 安装

以下内容不仅仅包含了 NumPy,更主要是针对 SciPy 的安装说明

安装方法包括:

方法在易用性,覆盖范围,旧版本的维护,系统范围与本地环境的使用以及控制方面有所不同。使用 pip 或 Anaconda 的 conda,您可以控制特定项目的软件包版本,以防止发生冲突。Conda 还可以控制非 Python 软件包,例如 MKL 或 HDF5。系统软件包管理器安装在整个计算机上,通常具有较旧的版本,并且可用版本不多。源代码编译要困难得多,但对于调试和开发而言是必需的。如果您不知道需要哪种安装方式,建议使用 Scientific Python Distribution Anaconda (opens new window).

# 科学的 Python 发行版 (推荐)

Python 发行版提供语言本身,以及最常用的软件包和工具。这些可下载文件需要很少的配置,几乎可以在所有设置上工作,并提供所有常用的科学 python 工具。

Anaconda (opens new window) 可在 Windows,Mac 和 Linux 上运行,提供了 1,500 多个 Python/R 程序包,超过 1500 万人在使用。Anaconda 提供了一个精简版本,Miniconda (opens new window),它仍然可以访问* conda *程序包管理器。

conda install numpy
1

其他选项包括:

# 通过 pip 安装

Python 带有内置的软件包管理系统 pip (opens new window)。Pip 可以安装,更新或删除任何官方软件包。

您可以通过命令行输入以下内容安装软件包:

python -m pip install --user numpy scipy matplotlib ipython jupyter pandas sympy nose
1

我们建议使用用户安装,将--user标志发送给 pip。pip为本地用户安装软件包,并且不写入系统目录。最好不要使用sudo pip,因为这种组合可能会引起问题。

Pip 访问 Python 程序包索引 PyPI (opens new window),该索引存储了将近 200,000 个项目以及该项目的所有先前版本。因为存储库保留以前的版本,所以您可以固定到一个版本,而不必担心更新会引起冲突。Pip 还可以在本地* virtualenv *或虚拟环境中安装软件包。

# 通过软件包管理器在系统范围内安装

系统软件包管理器可以安装最常见的 Python 软件包。他们为整个计算机安装软件包,通常使用旧版本,并且可用版本不多。

# Ubuntu and Debian

使用 apt-get:

sudo apt-get install python-numpy python-scipy python-matplotlib ipython ipython-notebook python-pandas python-sympy python-nose
1

# Fedora 22 and later

使用 dnf:

sudo dnf install numpy scipy python-matplotlib ipython python-pandas sympy python-nose atlas-devel
1

# Mac

Mac 没有预装的软件包管理器,但是您可以安装几个流行的软件包管理器。

对于 Macports (opens new window) 的 Python 3.5,在终端中执行以下命令:

sudo port install py35-numpy py35-scipy py35-matplotlib py35-ipython +notebook py35-pandas py35-sympy py35-nose
1

Homebrew (opens new window) 对 SciPy 生态系统的覆盖不完整,但确实安装了以下软件包:

brew install numpy scipy ipython jupyter
1

# 源码安装

有关从源代码构建的说明,请参阅 从源代码构建 (opens new window)。此信息主要对高级用户有用。

# 基础

NumPy 的主要对象是齐次多维数组。它是由非负整数元组索引的所有相同类型的元素表(通常为数字)。在 NumPy 中,维称为

例如,在 3D 空间[1、2、1]中的点的坐标只有一个轴。该轴上有 3 个元素,所以我们说它的长度为 3。在下方所示的示例中,数组有 2 个轴。第一轴的长度为 2,第二轴的长度为 3。

[[ 1., 0., 0.],
 [ 0., 1., 2.]]
1
2

NumPy 的数组类称为ndarray。它也被称作array。请注意,numpy.array与标准 Python 库array.array类不同,后者仅处理一维数组且功能较少。ndarray对象的更重要的属性是:

# 常用方法

# ndarray.ndim

数组的轴数(维)。

# ndarray.shape

数组的维。这是一个整数元组,指示每个维中数组的大小。对于具有* n 行和 m *列的矩阵,shape将为(n,m)。因此,形状元组的长度是轴数,ndim

# ndarray.size

数组元素的总数。这等于shape元素的乘积。

# ndarray.dtype

一个对象,描述数组中元素的类型。可以使用标准 Python 类型创建或指定 dtype。另外,NumPy 提供了自己的类型。例如numpy.int32numpy.int16numpy.float64

# ndarray.itemsize

数组中每个元素的大小以字节为单位。例如,float64类型的元素数组的itemsize大小为 8(=64/8),而complex32类型的元素数组的itemsize大小为 4(=32/8)。它等效于ndarray.dtype.itemsize

# ndarray.data

包含数组实际元素的缓冲区。通常,我们不需要使用此属性,因为我们将使用索引工具访问数组中的元素。

# 一个示例

>>> import numpy as np
>>> a = np.arange(15).reshape(3, 5)
>>> a
array([[ 0,  1,  2,  3,  4],
       [ 5,  6,  7,  8,  9],
       [10, 11, 12, 13, 14]])
>>> a.shape
(3, 5)
>>> a.ndim
2
>>> a.dtype.name
'int64'
>>> a.itemsize
8
>>> a.size
15
>>> type(a)
<class 'numpy.ndarray'>
>>> b = np.array([6, 7, 8])
>>> b
array([6, 7, 8])
>>> type(b)
<class 'numpy.ndarray'>
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23

# 数组

# 数组创建

有几种创建数组的方法。

例如,您可以使用array函数从常规 Python 列表或元组创建数组。根据序列中元素的类型决定返回数组的类型。

>>> 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')
1
2
3
4
5
6
7
8
9

常见错误在于调用array时带有多个参数,而不是提供单个序列作为参数。

>>> a = np.array(1,2,3,4)    # WRONG
Traceback (most recent call last):
...
ValueError: only 2 non-keyword arguments accepted
>>> a = np.array([1,2,3,4])  # RIGHT
1
2
3
4
5

array将序列的序列转换为二维数组,将序列的序列的序列转换为三维数组,依此类推。

>>> b = np.array([(1.5,2,3), (4,5,6)])
>>> b
array([[ 1.5,  2. ,  3. ],
       [ 4. ,  5. ,  6. ]])
1
2
3
4

数组的类型也可以在创建时明确指定:

>>> c = np.array( [ [1,2], [3,4] ], dtype=complex )
>>> c
array([[ 1.+0.j,  2.+0.j],
       [ 3.+0.j,  4.+0.j]])
1
2
3
4

通常,数组的元素最初是未知的,但是其大小是已知的。因此,NumPy 提供了几个函数来创建具有初始占位符内容的数组。这样就减少了增加阵列的必要性,这是一项较大花销的操作。

函数zeros创建一个由零组成的数组,函数one创建一个由 1 组成的数组,而函数empty创建一个数组,其初始内容是随机的,并取决于内存的状态。默认情况下,创建的数组的 dtype 为float64

>>> 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 )                # dtype can also be specified
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) )                                 # uninitialized
array([[  3.73603959e-262,   6.02658058e-154,   6.55490914e-260],  # may vary
       [  5.30498948e-313,   3.14673309e-307,   1.00000000e+000]])
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15

为了创建数字序列,NumPy 提供了arange函数,该函数类似于 Python 内置的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])
1
2
3
4

arange与浮点参数一起使用时,由于有限的浮点精度,通常无法预测获得的元素数量。由于这个原因,通常最好使用函数 linspace 来接收所需数量的元素作为参数,替代上述步骤:

>>> from numpy import pi
>>> np.linspace( 0, 2, 9 )                 # 9 numbers from 0 to 2
array([ 0.  ,  0.25,  0.5 ,  0.75,  1.  ,  1.25,  1.5 ,  1.75,  2.  ])
>>> x = np.linspace( 0, 2*pi, 100 )        # useful to evaluate function at lots of points
>>> f = np.sin(x)
1
2
3
4
5

另请参阅

array, zeros, zeros_like, ones, ones_like, empty, empty_like, arange, linspace, numpy.random.Generator.rand, numpy.random.Generator.randn, fromfunction, fromfile

# 打印数组

当您打印数组时,NumPy 以类似于嵌套列表的方式显示它,但具有以下布局:

  • 最后一个轴从左到右打印,
  • 倒数第二个从上到下打印,
  • 其余的也从上到下打印,每个切片之间用空行隔开。

然后将一维数组打印为行,将二维打印为矩阵,将三维打印为矩阵列表。

>>> a = np.arange(6)                         # 1d array
>>> print(a)
[0 1 2 3 4 5]
>>>
>>> b = np.arange(12).reshape(4,3)           # 2d array
>>> print(b)
[[ 0  1  2]
 [ 3  4  5]
 [ 6  7  8]
 [ 9 10 11]]
>>>
>>> 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]]]
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19

请参阅后文以获取有关reshape的更多详细信息。

如果数组太大而无法打印,则 NumPy 会自动跳过数组的中心部分,仅打印角点:

>>> print(np.arange(10000))
[   0    1    2 ... 9997 9998 9999]
>>>
>>> print(np.arange(10000).reshape(100,100))
[[   0    1    2 ...   97   98   99]
 [ 100  101  102 ...  197  198  199]
 [ 200  201  202 ...  297  298  299]
 ...
 [9700 9701 9702 ... 9797 9798 9799]
 [9800 9801 9802 ... 9897 9898 9899]
 [9900 9901 9902 ... 9997 9998 9999]]
1
2
3
4
5
6
7
8
9
10
11

若要禁用此行为并强制 NumPy 打印整个数组,可以使用set_printoptions更改打印选项。

>>> 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
2
3
4
5
6
7
8
9
10
11
12
13

与许多矩阵语言不同,乘积运算符*在 NumPy 数组中按元素进行运算。可以使用@运算符(在 python> = 3.5 中)或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
2
3
4
5
6
7
8
9
10
11
12
13

某些操作(例如+=*=)可以修改现有数组,而不是创建新数组。

>>> 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.UFuncTypeError: Cannot cast from dtype('float64') to dtype('int64')  # IGNORE_EXCEPTION_DETAIL
1
2
3
4
5
6
7
8
9
10
11
12
13
14

当使用不同类型的数组进行操作时,结果数组的类型对应于更通用或更精确的数组(这种行为称为向上转换)。

>>> 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'
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15

许多一元运算(例如计算数组中所有元素的总和)都作为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
1
2
3
4
5
6
7
8
9
10

默认情况下,这些操作适用于数组,就好像它是一个数字列表一样,而不管其形状如何。但是,通过指定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]])
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16

# 通用功能

NumPy 提供了熟悉的数学函数,例如 sin,cos 和 exp。在 NumPy 中,这些称为“通用函数”(ufunc)。在 NumPy 中,这些函数在数组上逐个元素操作,生成数组输出。

>>> B = np.arange(3)
>>> B
array([0, 1, 2])
>>> np.exp(B)
array([ 1.        ,  2.71828183,  7.3890561 ])
>>> np.sqrt(B)
array([ 0.        ,  1.        ,  1.41421356])
>>> C = np.array([2., -1., 4.])
>>> np.add(B, C)
array([ 2.,  0.,  6.])
1
2
3
4
5
6
7
8
9
10

另请参阅

all, any, apply_along_axis, argmax, argmin, argsort, average, bincount, ceil, clip, conj, corrcoef, cov, cross, cumprod, cumsum, diff, dot, floor, inner, invert, lexsort, max, maximum, mean, median, min, minimum, nonzero, outer, prod, re, round, sort, std, sum, trace, transpose, var, vdot, vectorize, where

# 索引,切片和迭代

一维数组可以像列表和其他 Python 序列一样被索引,切片和迭代。

>>> a = np.arange(10)**3
>>> a
array([  0,   1,   8,  27,  64, 125, 216, 343, 512, 729])
>>> a[2]
8
>>> a[2:5]
array([ 8, 27, 64])
# equivalent to a[0:6:2] = 1000;
# from start to position 6, exclusive, set every 2nd element to 1000
>>> a[:6:2] = 1000
>>> a
array([1000,    1, 1000,   27, 1000,  125,  216,  343,  512,  729])
>>> a[ : :-1]                                 # reversed a
array([  729,  512,  343,  216,  125, 1000,   27, 1000,    1, 1000])
>>> for i in a:
...     print(i**(1/3.))
...
9.999999999999998
1.0
9.999999999999998
3.0
9.999999999999998
4.999999999999999
5.999999999999999
6.999999999999999
7.999999999999999
8.999999999999998
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27

多维数组每个轴可以有一个索引。这些索引以元组给出,并用逗号分隔:

>>> def f(x,y):
...     return 10*x+y
...
>>> b = np.fromfunction(f,(5,4),dtype=int)
>>> b
array([[ 0,  1,  2,  3],
       [10, 11, 12, 13],
       [20, 21, 22, 23],
       [30, 31, 32, 33],
       [40, 41, 42, 43]])
>>> b[2,3]
23
>>> b[0:5, 1]                       # each row in the second column of b
array([ 1, 11, 21, 31, 41])
>>> b[ : ,1]                        # equivalent to the previous example
array([ 1, 11, 21, 31, 41])
>>> b[1:3, : ]                      # each column in the second and third row of b
array([[10, 11, 12, 13],
       [20, 21, 22, 23]])
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19

如果提供的索引数少于轴数,则丢失的索引数将视为完整切片:

>>> b[-1]                                  # the last row. Equivalent to b[-1,:]
array([40, 41, 42, 43])
1
2

b[i]中括号内的表达式被视为i,一个 i 后跟:代表轴剩余的尽可能多的实例。NumPy 还允许您使用点,写为b[i,...]

(...)代表产生完整索引元组所需的多个冒号。例如,如果x是具有 5 个轴的数组,则

  • x[1,2,...]等效于x[1,2,:,:,:]
  • x[...,3]等效于x[:,:,:,:,3]
  • x[4,...,5,:]等效于x[4,:,:,5,:]
>>> c = np.array( [[[  0,  1,  2],               # a 3D array (two stacked 2D arrays)
...                 [ 10, 12, 13]],
...                [[100,101,102],
...                 [110,112,113]]])
>>> c.shape
(2, 2, 3)
>>> c[1,...]                                   # same as c[1,:,:] or c[1]
array([[100, 101, 102],
       [110, 112, 113]])
>>> c[...,2]                                   # same as c[:,:,2]
array([[  2,  13],
       [102, 113]])
1
2
3
4
5
6
7
8
9
10
11
12

相对于第一个轴迭代多维数组:

>>> for row in b:
...     print(row)
...
[0 1 2 3]
[10 11 12 13]
[20 21 22 23]
[30 31 32 33]
[40 41 42 43]
1
2
3
4
5
6
7
8

但是,如果要对数组中的每个元素执行操作,则可以使用flat属性,它是数组所有元素上的迭代器:

>>> for element in b.flat:
...     print(element)
...
0
1
2
3
10
11
12
13
20
21
22
23
30
31
32
33
40
41
42
43
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23

另请参阅

Indexing, Indexing (reference), newaxis, ndenumerate, indices

# 形状控制

# 改变数组形状

一个数组的形状由每个轴上的元素的数量给出:

>>> a = np.floor(10*rg.random((3,4)))
>>> a
array([[3., 7., 3., 4.],
       [1., 4., 2., 2.],
       [7., 2., 4., 9.]])
>>> a.shape
(3, 4)
1
2
3
4
5
6
7

数组的形状可以通过各种命令进行更改。请注意,以下三个命令都返回修改过的数组,但不更改原始数组:

>>> a.ravel()  # returns the array, flattened
array([3., 7., 3., 4., 1., 4., 2., 2., 7., 2., 4., 9.])
>>> a.reshape(6,2)  # returns the array with a modified shape
array([[3., 7.],
       [3., 4.],
       [1., 4.],
       [2., 2.],
       [7., 2.],
       [4., 9.]])
>>> a.T  # returns the array, transposed
array([[3., 1., 7.],
       [7., 4., 2.],
       [3., 2., 4.],
       [4., 2., 9.]])
>>> a.T.shape
(4, 3)
>>> a.shape
(3, 4)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18

ravel()产生的数组中元素的顺序通常是“C-style”,即最右边的索引“变化最快”,因此[0,0]后面的元素是[0,1]。如果数组被重塑为其他形状,则数组将再次被视为“C 样式”。NumPy 通常创建按此顺序存储的数组,因此ravel()通常不需要复制它的参数,但是如果数组是通过获取另一个数组的片段或使用不寻常的选项创建的,则可能需要复制它。还可以使用可选参数指示函数ravel()reshape()使用 FORTRAN 样式的数组,其最左边的索引变化最快。

reshape函数使用修改后的形状作为返回参数,而ndarray.resize方法修改数组本身:

>>> a
array([[3., 7., 3., 4.],
       [1., 4., 2., 2.],
       [7., 2., 4., 9.]])
>>> a.resize((2,6))
>>> a
array([[3., 7., 3., 4., 1., 4.],
       [2., 2., 7., 2., 4., 9.]])
1
2
3
4
5
6
7
8

如果在整形操作中将维指定为-1,则会自动计算目标维数:

>>> a.reshape(3,-1)
array([[3., 7., 3., 4.],
       [1., 4., 2., 2.],
       [7., 2., 4., 9.]])
1
2
3
4

另请参阅

ndarray.shape, reshape, resize, ravel

# 将不同的数组堆叠在一起

几个数组可以沿不同的轴堆叠在一起:

>>> a = np.floor(10*rg.random((2,2)))
>>> a
array([[9., 7.],
       [5., 2.]])
>>> b = np.floor(10*rg.random((2,2)))
>>> b
array([[1., 9.],
       [5., 1.]])
>>> np.vstack((a,b))
array([[9., 7.],
       [5., 2.],
       [1., 9.],
       [5., 1.]])
>>> np.hstack((a,b))
array([[9., 7., 1., 9.],
       [5., 2., 5., 1.]])
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16

函数column_stack将 1 维数组作为列堆叠到 2 维数组中。它仅对于二维数组相当于hstack

>>> from numpy import newaxis
>>> np.column_stack((a,b))     # with 2D arrays
array([[9., 7., 1., 9.],
       [5., 2., 5., 1.]])
>>> a = np.array([4.,2.])
>>> b = np.array([3.,8.])
>>> np.column_stack((a,b))     # returns a 2D array
array([[ 4., 3.],
       [ 2., 8.]])
>>> np.hstack((a,b))           # the result is different
array([ 4., 2., 3., 8.])
>>> a[:,newaxis]               # this allows to have a 2D columns vector
array([[ 4.],
       [ 2.]])
>>> np.column_stack((a[:,newaxis],b[:,newaxis]))
array([[ 4.,  3.],
       [ 2.,  8.]])
>>> np.hstack((a[:,newaxis],b[:,newaxis]))   # the result is the same
array([[ 4.,  3.],
       [ 2.,  8.]])
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20

另一方面,对于任何输入数组,函数row_stack都等价于vstack。实际上,row_stackvstack的别名:

>>> np.column_stack is np.hstack
False
>>> np.row_stack is np.vstack
True
1
2
3
4

一般来说,对于具有两个以上维度的数组,hstack沿它们的第二轴堆叠,vstack沿它们的第一轴堆叠,并且concatenate允许一个可选的参数,给出concatenate应该发生的轴的值。

请注意
在复杂的情况下,r_c_对于通过沿一个轴堆叠数字来创建数组是有用的。它们允许使用范围符号(“:”)

>>> np.r_[1:4,0,4]
array([1, 2, 3, 0, 4])
1
2

当以数组作为参数使用时,r_c_类似于vstackhstack的默认行为,但是允许一个可选的参数,指出用于连接的轴的值。

另请参阅

hstack, vstack, column_stack, concatenate, c_, r_

# 将一个数组拆分为几个较小的数组

使用hsplit,可以通过指定要返回的相同形状的数组的数量,或者通过指定在其中发生除法的列来将数组沿水平轴拆分:

>>> a = np.floor(10*rg.random((2,12)))
>>> a
array([[6., 7., 6., 9., 0., 5., 4., 0., 6., 8., 5., 2.],
       [8., 5., 5., 7., 1., 8., 6., 7., 1., 8., 1., 0.]])
# Split a into 3
>>> np.hsplit(a,3)
[array([[6., 7., 6., 9.],
       [8., 5., 5., 7.]]), array([[0., 5., 4., 0.],
       [1., 8., 6., 7.]]), array([[6., 8., 5., 2.],
       [1., 8., 1., 0.]])]
# Split a after the third and the fourth column
>>> np.hsplit(a,(3,4))
[array([[6., 7., 6.],
       [8., 5., 5.]]), array([[9.],
       [7.]]), array([[0., 5., 4., 0., 6., 8., 5., 2.],
       [1., 8., 6., 7., 1., 8., 1., 0.]])]
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16

vsplit沿垂直轴拆分,而array_split允许指定沿哪个轴拆分。

# 复制和 Views

当操作和操作数组时,它们的数据有时会被复制到一个新数组中,有时则不会。对于初学者来说,这常常是一个困惑的来源。有三种情况:

# 完全没有复制

简单的赋值不会复制数组对象或其数据。

>>> a = np.arange(12)
>>> b = a            # no new object is created
>>> b is a           # a and b are two names for the same ndarray object
True
>>> b.shape = 3,4    # changes the shape of a
>>> a.shape
(3, 4)
1
2
3
4
5
6
7

Python 将可变对象作为引用传递,因此函数调用不进行复制。

>>> def f(x):
...     print(id(x))
...
>>> id(a)                           # id is a unique identifier of an object
148293216  # may vary
>>> f(a)
148293216  # may vary
1
2
3
4
5
6
7

# View 或浅复制

不同的数组对象可以共享相同的数据。view方法创建一个新的数组对象来查看相同的数据。

>>> c = a.view()
>>> c is a
False
>>> c.base is a                        # c is a view of the data owned by a
True
>>> c.flags.owndata
False
>>>
>>> c.shape = 2,6                      # a's shape doesn't change
>>> a.shape
(3, 4)
>>> c[0,4] = 1234                      # a's data changes
>>> a
array([[   0,    1,    2,    3],
       [1234,    5,    6,    7],
       [   8,    9,   10,   11]])
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16

切片数组将返回其view

>>> s = a[ : , 1:3]     # spaces added for clarity; could also be written "s = a[:,1:3]"
>>> s[:] = 10           # s[:] is a view of s. Note the difference between s=10 and s[:]=10
>>> a
array([[   0,   10,   10,    3],
       [1234,   10,   10,    7],
       [   8,   10,   10,   11]])
1
2
3
4
5
6

# 深拷贝

copy方法生成数组及其数据的完整副本。

>>> d = a.copy()                          # a new array object with new data is created
>>> d is a
False
>>> d.base is a                           # d doesn't share anything with a
False
>>> d[0,0] = 9999
>>> a
array([[   0,   10,   10,    3],
       [1234,   10,   10,    7],
       [   8,   10,   10,   11]])
1
2
3
4
5
6
7
8
9
10

有时,如果不再需要原始数组,则应在切片后调用copy。例如,假设a是一个巨大的中间结果,而最终结果b只包含a的一小部分,则应在使用切片构造b时进行深度复制:

>>> a = np.arange(int(1e8))
>>> b = a[:100].copy()
>>> del a  # the memory of ``a`` can be released.
1
2
3

如果改用b=a[:100],则 b 引用 a,即使执行del aa也将保留在内存中。

# 功能和方法概述

下面是按类别排序的一些有用的 NumPy 函数和方法名称的列表。完整列表请参见 Routones (opens new window)

Array Creation arange, array, copy, empty, empty_like, eye, fromfile, fromfunction, identity, linspace, logspace, mgrid, ogrid, ones, ones_like, r_, zeros, zeros_like

Conversions ndarray.astype, atleast_1d, atleast_2d, atleast_3d, mat

Manipulations array_split, column_stack, concatenate, diagonal, dsplit, dstack, hsplit, hstack, ndarray.item, newaxis, ravel, repeat, reshape, resize, squeeze, swapaxes, take, transpose, vsplit, vstack

Questions all, any, nonzero, where

Ordering argmax, argmin, argsort, max, min, ptp, searchsorted, sort

Operations choose, compress, cumprod, cumsum, inner, ndarray.fill, imag, prod, put, putmask, real, sum

Basic Statistics cov, mean, std, var

Basic Linear Algebra cross, dot, outer, linalg.svd, vdot

# 广播规则简介

广播允许通用函数以有意义的方式处理不完全相同形状的输入。

广播的第一条规则是,如果所有输入数组的维数都不相同,则将在较小数组的形状前重复添加一个“1”,直到所有数组的维数都相同。

广播的第二条规则确保沿特定维度大小为 1 的数组的行为与沿该维度形状最大的数组的行为相同。假定数组元素的值沿“广播”数组维度是相同的。

个人笔记

广播的第二条规则可理解为若一个 3x3 与 1x3 数组相加:

[ [1,2,3],               | 1 2 3 | + | 1 1 1 |   | 2 3 4 |
  [4,5,6],   + [1,1,1] = | 4 5 6 | + | 1 1 1 | = | 5 6 7 |
  [7,8,9] ]              | 7 8 9 | + | 1 1 1 |   | 8 9 10|
1
2
3

则将“广播数组”延伸

应用广播规则后,所有数组的大小必须匹配。更多细节可以在 广播 找到。

NumPy 提供比常规 Python 序列更多的索引设施。除了使用整数和切片索引,正如我们以前看到的,数组可以用整数数组和布尔数组来索引。

# 高级索引技巧

# 使用索引数组建立索引

>>> a = np.arange(12)**2                       # the first 12 square numbers
>>> i = np.array( [ 1,1,3,8,5 ] )              # an array of indices
>>> a[i]                                       # the elements of a at the positions i
array([ 1,  1,  9, 64, 25])
>>>
>>> j = np.array( [ [ 3, 4], [ 9, 7 ] ] )      # a bidimensional array of indices
>>> a[j]                                       # the same shape as j
array([[ 9, 16],
       [81, 49]])
1
2
3
4
5
6
7
8
9

当被索引数组a为多维时,单个索引数组指a的第一维。 下面的示例通过使用调色板将标签图像转换为彩色图像来显示此行为。

>>> palette = np.array( [ [0,0,0],                # black
...                       [255,0,0],              # red
...                       [0,255,0],              # green
...                       [0,0,255],              # blue
...                       [255,255,255] ] )       # white
>>> image = np.array( [ [ 0, 1, 2, 0 ],           # each value corresponds to a color in the palette
...                     [ 0, 3, 4, 0 ]  ] )
>>> palette[image]                            # the (2,4,3) color image
array([[[  0,   0,   0],
        [255,   0,   0],
        [  0, 255,   0],
        [  0,   0,   0]],
       [[  0,   0,   0],
        [  0,   0, 255],
        [255, 255, 255],
        [  0,   0,   0]]])
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16

我们还可以为多个维度提供索引。每个维度的索引数组必须具有相同的形状。

>>> a = np.arange(12).reshape(3,4)
>>> a
array([[ 0,  1,  2,  3],
       [ 4,  5,  6,  7],
       [ 8,  9, 10, 11]])
>>> i = np.array( [ [0,1],                        # indices for the first dim of a
...                 [1,2] ] )
>>> j = np.array( [ [2,1],                        # indices for the second dim
...                 [3,3] ] )
>>>
>>> a[i,j]                                     # i and j must have equal shape
array([[ 2,  5],
       [ 7, 11]])
>>>
>>> a[i,2]
array([[ 2,  6],
       [ 6, 10]])
>>>
>>> a[:,j]                                     # i.e., a[ : , j]
array([[[ 2,  1],
        [ 3,  3]],
       [[ 6,  5],
        [ 7,  7]],
       [[10,  9],
        [11, 11]]])
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25

个人笔记

a[i,j]可视为ia取第一维(最左侧),随后ja[i]取第二维索引。对于二维数组,可视为先按“行”再按“列”索引

自然地,我们可以将 i 和 j 放在一个序列中(例如一个列表),然后对列表进行索引。

>>> l = (i, j)
# equivalent to a[i,j]
>>> a[l]
array([[ 2,  5],
       [ 7, 11]])
1
2
3
4
5

但是,我们无法通过将 i 和 j 放入数组来完成此操作,因为该数组将被解释为索引 a 的第一维。

>>> s = np.array( [i,j] )

# not what we want
>>> a[s]
Traceback (most recent call last):
  File "<stdin>", line 1, in ?
IndexError: index (3) out of range (0<=index<=2) in dimension 0

# same as a[i,j]
>>> a[tuple(s)]
array([[ 2,  5],
       [ 7, 11]])
1
2
3
4
5
6
7
8
9
10
11
12

但是,我们不能通过将ij放入数组来做到这一点,因为该数组将被解释为索引的a第一个维度

>>> s = np.array( [i,j] )

# not what we want
>>> a[s]
Traceback (most recent call last):
  File "<stdin>", line 1, in ?
IndexError: index (3) out of range (0<=index<=2) in dimension 0

# same as a[i,j]
>>> a[tuple(s)]
array([[ 2,  5],
       [ 7, 11]])
1
2
3
4
5
6
7
8
9
10
11
12

使用数组建立索引的另一种常见用法是搜索时间相关序列的最大值:

>>> time = np.linspace(20, 145, 5)                 # time scale
>>> data = np.sin(np.arange(20)).reshape(5,4)      # 4 time-dependent series
>>> time
array([  20.  ,   51.25,   82.5 ,  113.75,  145.  ])
>>> data
array([[ 0.        ,  0.84147098,  0.90929743,  0.14112001],
       [-0.7568025 , -0.95892427, -0.2794155 ,  0.6569866 ],
       [ 0.98935825,  0.41211849, -0.54402111, -0.99999021],
       [-0.53657292,  0.42016704,  0.99060736,  0.65028784],
       [-0.28790332, -0.96139749, -0.75098725,  0.14987721]])

# index of the maxima for each series
>>> ind = data.argmax(axis=0)
>>> ind
array([2, 0, 3, 1])

# times corresponding to the maxima
>>> time_max = time[ind]
>>>
>>> data_max = data[ind, range(data.shape[1])] # => data[ind[0],0], data[ind[1],1]...

>>> time_max
array([  82.5 ,   20.  ,  113.75,   51.25])
>>> data_max
array([ 0.98935825,  0.84147098,  0.99060736,  0.6569866 ])

>>> np.all(data_max == data.max(axis=0))
True
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28

您还可以将索引与数组一起用作分配给以下对象的目标:

>>> a = np.arange(5)
>>> a
array([0, 1, 2, 3, 4])
>>> a[[1,3,4]] = 0
>>> a
array([0, 0, 2, 0, 0])
1
2
3
4
5
6

但是,当索引列表包含重复项时,分配将完成几次,而留下最后一个值:

>>> a = np.arange(5)
>>> a[[0,0,2]]=[1,2,3]
>>> a
array([2, 1, 3, 3, 4])
1
2
3
4

这足够合理,但是请注意是否要使用 Python 的+=构造,因为它可能无法满足您的期望:

>>> a = np.arange(5)
>>> a[[0,0,2]]+=1
>>> a
array([1, 1, 3, 3, 4])
1
2
3
4

即使 0 在索引列表中出现两次,第 0 个元素也仅递增一次。这是因为 Python 要求a += 1等于同a = a + 1

# 使用布尔数组建立索引

当我们使用(整数)索引数组对数组进行索引时,我们提供了要选择的索引列表。对于布尔索引,方法是不同的;我们显式地选择数组中需要的项和不需要的项。

>>> a = np.arange(12).reshape(3,4)
>>> b = a > 4
>>> b                                          # b is a boolean with a's shape
array([[False, False, False, False],
       [False,  True,  True,  True],
       [ True,  True,  True,  True]])
>>> a[b]                                       # 1d array with the selected elements
array([ 5,  6,  7,  8,  9, 10, 11])
1
2
3
4
5
6
7
8

此属性在分配时非常有用:

>>> a[b] = 0                                   # All elements of 'a' higher than 4 become 0
>>> a
array([[0, 1, 2, 3],
       [4, 0, 0, 0],
       [0, 0, 0, 0]])
1
2
3
4
5

您可以查看下面的示例,看看如何使用布尔索引来生成 曼德尔布罗特 (opens new window) 的图像:

>>> import numpy as np
>>> import matplotlib.pyplot as plt
>>> def mandelbrot( h,w, maxit=20 ):
...     """Returns an image of the Mandelbrot fractal of size (h,w)."""
...     y,x = np.ogrid[ -1.4:1.4:h*1j, -2:0.8:w*1j ]
...     c = x+y*1j
...     z = c
...     divtime = maxit + np.zeros(z.shape, dtype=int)
...
...     for i in range(maxit):
...         z = z**2 + c
...         diverge = z*np.conj(z) > 2**2            # who is diverging
...         div_now = diverge & (divtime==maxit)  # who is diverging now
...         divtime[div_now] = i                  # note when
...         z[diverge] = 2                        # avoid diverging too much
...
...     return divtime
>>> plt.imshow(mandelbrot(400,400))
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18

mandelbrot

使用布尔值建立索引的第二种方式与整数索引更相似; 对于数组的每个维度,我们提供一个一维布尔数组,选择所需的切片:

>>> a = np.arange(12).reshape(3,4)
>>> b1 = np.array([False,True,True])             # first dim selection
>>> b2 = np.array([True,False,True,False])       # second dim selection
>>>
>>> a[b1,:]                                   # selecting rows
array([[ 4,  5,  6,  7],
       [ 8,  9, 10, 11]])
>>>
>>> a[b1]                                     # same thing
array([[ 4,  5,  6,  7],
       [ 8,  9, 10, 11]])
>>>
>>> a[:,b2]                                   # selecting columns
array([[ 0,  2],
       [ 4,  6],
       [ 8, 10]])
>>>
>>> a[b1,b2]                                  # a weird thing to do
array([ 4, 10])
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19

请注意,一维布尔数组的长度必须与要切片的维(或轴)的长度一致。在前面的示例中,b1的长度为 3(a中的行数),b2(的长度为 4)适合于索引a的第二轴(列)。

# ix_() 函数

ix_函数可用于组合不同的向量,以获得每个 n-uplet 的结果。例如,如果您要计算从向量 a,b 和 c 中选取的所有三元组的 a+b*c

>>> a = np.array([2,3,4,5])
>>> b = np.array([8,5,4])
>>> c = np.array([5,4,6,8,3])
>>> ax,bx,cx = np.ix_(a,b,c)
>>> ax
array([[[2]],
       [[3]],
       [[4]],
       [[5]]])
>>> bx
array([[[8],
        [5],
        [4]]])
>>> cx
array([[[5, 4, 6, 8, 3]]])
>>> ax.shape, bx.shape, cx.shape
((4, 1, 1), (1, 3, 1), (1, 1, 5))
>>> result = ax+bx*cx
>>> result
array([[[42, 34, 50, 66, 26],
        [27, 22, 32, 42, 17],
        [22, 18, 26, 34, 14]],
       [[43, 35, 51, 67, 27],
        [28, 23, 33, 43, 18],
        [23, 19, 27, 35, 15]],
       [[44, 36, 52, 68, 28],
        [29, 24, 34, 44, 19],
        [24, 20, 28, 36, 16]],
       [[45, 37, 53, 69, 29],
        [30, 25, 35, 45, 20],
        [25, 21, 29, 37, 17]]])
>>> result[3,2,4]
17
>>> a[3]+b[2]*c[4]
17
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35

个人笔记

使用ix_,可以快速构造索引数组,该索引数组将对叉积进行索引。返回数组。

a[np.ix_([1,3],[2,5])] 等同于 [[a[1,2] a[1,5]], [a[3,2] a[3,5]]]

您还可以按以下方式实现 reduce:

>>> def ufunc_reduce(ufct, *vectors):
...    vs = np.ix_(*vectors)
...    r = ufct.identity
...    for v in vs:
...        r = ufct(r,v)
...    return r
1
2
3
4
5
6

and then use it as:

>>> ufunc_reduce(np.add,a,b,c)
array([[[15, 14, 16, 18, 13],
        [12, 11, 13, 15, 10],
        [11, 10, 12, 14,  9]],
       [[16, 15, 17, 19, 14],
        [13, 12, 14, 16, 11],
        [12, 11, 13, 15, 10]],
       [[17, 16, 18, 20, 15],
        [14, 13, 15, 17, 12],
        [13, 12, 14, 16, 11]],
       [[18, 17, 19, 21, 16],
        [15, 14, 16, 18, 13],
        [14, 13, 15, 17, 12]]])
1
2
3
4
5
6
7
8
9
10
11
12
13

与普通的 ufunc.reduce 相比,该版本的 reduce 的优点在于,它利用广播规则来避免创建一个参数数组,该参数数组的大小乘以输出数乘以向量数。

# 用字符串索引

See Structured arrays (opens new window).

# 线性代数

工作正在进行中。 基本线性代数将包含在此处。

# 简单的数组操作

有关更多信息,请参见 numpy 文件夹中的 linalg.py。

>>> import numpy as np
>>> a = np.array([[1.0, 2.0], [3.0, 4.0]])
>>> print(a)
[[1. 2.]
 [3. 4.]]

>>> a.transpose()
array([[ 1.,  3.],
       [ 2.,  4.]])

>>> np.linalg.inv(a)
array([[-2. ,  1. ],
       [ 1.5, -0.5]])

>>> u = np.eye(2) # unit 2x2 matrix; "eye" represents "I"
>>> u
array([[ 1.,  0.],
       [ 0.,  1.]])
>>> j = np.array([[0.0, -1.0], [1.0, 0.0]])

>>> j @ j        # matrix product
array([[-1.,  0.],
       [ 0., -1.]])

>>> np.trace(u)  # trace
2.0

>>> y = np.array([[5.], [7.]])
>>> np.linalg.solve(a, y)
array([[-3.],
       [ 4.]])

>>> np.linalg.eig(j)
(array([ 0.+1.j,  0.-1.j]), array([[ 0.70710678+0.j        ,  0.70710678-0.j        ],
       [ 0.00000000-0.70710678j,  0.00000000+0.70710678j]]))
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
Parameters:
    square matrix
Returns
    The eigenvalues, each repeated according to its multiplicity.
    The normalized (unit "length") eigenvectors, such that the
    column ``v[:,i]`` is the eigenvector corresponding to the
    eigenvalue ``w[i]`` .
1
2
3
4
5
6
7

# “自动”调整形状

要更改数组的形状,您可以忽略其中一个维,然后其将被自动推断:

>>> a = np.arange(30)
>>> a.shape = 2,-1,3  # -1 means "whatever is needed"
>>> a.shape
(2, 5, 3)
>>> a
array([[[ 0,  1,  2],
        [ 3,  4,  5],
        [ 6,  7,  8],
        [ 9, 10, 11],
        [12, 13, 14]],
       [[15, 16, 17],
        [18, 19, 20],
        [21, 22, 23],
        [24, 25, 26],
        [27, 28, 29]]])
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15

# 向量堆叠

我们如何从大小相等的行向量列表中构建 2D 数组?在 MATLAB 中这很容易:如果xy是两个相同长度的向量,则只需要m=[x;y]。在 NumPy 中,这可以通过column_stackdstackhstackvstack函数来实现,具体取决于要进行堆叠的维度。例如:

>>> x = np.arange(0,10,2)
>>> y = np.arange(5)
>>> m = np.vstack([x,y])
>>> m
array([[0, 2, 4, 6, 8],
       [0, 1, 2, 3, 4]])
>>> xy = np.hstack([x,y])
>>> xy
array([0, 2, 4, 6, 8, 0, 1, 2, 3, 4])
1
2
3
4
5
6
7
8
9

另请参阅

NumPy for Matlab users

# 柱状图

用于数组的 NumPy histogram函数返回一对向量:数组的直方图和 bin 边的向量。注意:matplotlib还具有构建直方图的功能(在 Matlab 中称为hist),与 NumPy 中的直方图不同。主要区别在于pylab.hist自动绘制直方图,而numpy.histogram仅生成数据。

>>> import numpy as np
>>> rg = np.random.default_rng(1)
>>> import matplotlib.pyplot as plt
>>> # Build a vector of 10000 normal deviates with variance 0.5^2 and mean 2
>>> mu, sigma = 2, 0.5
>>> v = rg.normal(mu,sigma,10000)
>>> # Plot a normalized histogram with 50 bins
>>> plt.hist(v, bins=50, density=1)       # matplotlib version (plot)
>>> # Compute the histogram with numpy and then plot it
>>> (n, bins) = np.histogram(v, bins=50, density=True)  # NumPy version (no plot)
>>> plt.plot(.5*(bins[1:]+bins[:-1]), n)
1
2
3
4
5
6
7
8
9
10
11

histogram

# 进阶阅读

Last Updated: 2023-10-29T08:26:04.000Z