# NumPy初学者教程
### 什么是MumPy?
NumPy(Numerical Python) 是一份用于几乎所有科学与工程领域的开源Python库。它是Python处理数字化数据的普遍标准,也是科学领域的Python以及PyData生态系统的核心。NumPy用户包括从初级编码人员到经验丰富的研究人员进行最先进的科学和工业研究和开发的每个人。NumPy广泛用于Pandas,ScuPy,Matplotlib,Scikit-learn,scikit-image以及其他大多数数据科学和科学Python包。
NumPy库包含多维数组和矩阵数据结构(你会在后续的章节了解到它)。它为 ndarray(一个齐构的 n 维数组对象)提供了对其进行有效操作的方法。NumPy可用于对数组执行各种数学运算。它为Python添加了强大的数据结构,保证了数组和矩阵的有效计算,并提供了一个庞大的高级数学函数库,可以在这些数组和矩阵上运行。
### 安装NumPy
要安装 NumPy,我们强烈建议使用科学的 Python 发行版。如果你正在寻找在操作系统上安装 NumPy 的完整说明,请参阅[安装 NumPy](https://numpy.org/install/)。
```python
conda install numpy
```
或
```python
pip install numpy
```
### 如何导入NumPy
为访问NumPy和其方法函数,你导入它的Python代码,如下所示:
```python
import numpy as np
```
我们将np作为导入后的缩写名称,以便在使用NumPy时提高代码的可读性。这是你应该遵循的广泛采用约定,以便使用你代码的任何人都可以轻松理解它。
### 阅读示例代码
如果你不习惯阅读包含大量代码的教程,你可能不知道如何解释如下所示的代码块:
```py
>>>a = np.arange(6)
>>>a2 = a[np.newaxis, :]
>>>a2.shape
(1, 6)
```
你可能不熟悉这种风格,但是它非常容易理解。如果你看到`>>>`,就代表需要输入,即要输入的代码。而所有前面没有`>>>`的内容都代表输出,即运行代码的结果。 在命令行中运行`python`时,你会看见这种风格。但是你没有使用IPython,可能会看见一种不同的风格。注意,它不是代码的一部分,如果输入或粘贴到Python shell中会导致错误,但是可以安全地输入或粘贴到IPython shell中,因为`>>>`会被忽略。
### Python's list 与 NumPy数组有什么不同?
NumPy为你提供了大量快速有效的方法来创建数组并在其中操作数字数据。Python list可以用一个单列表包含不同的数据类型,而NumPy数组中的所有元素应该是同质的。(换言之,NumPy数组中的元素数据类型应该是一样的。)如果数组不是同质的,那么要在数组上进行的数学运算的效率就会非常低。
**为什么使用NumPy?**
NumPy数组相比于Python list更加快速、紧凑。数组消耗内存较少,使用起来也很方便。NumPy使用更少的内幕出才能来存储数据,并且提供了一个指定数据类型的机制。这使得代码可以得到进一步的优化。
### 什么是数组?
数组是NumPy库的一个核心数据结构。数组是一个值的网格,它包含了关于原始数据的信息:如何定位一个元素,以及如何解释一个元素。它有一个由元素组成的网格,可以用各种方式进行索引。这些元素都是同一类型,被称为数组dtype。
一个数组可以被一个非负整数的元组、布尔、另一个数组或整数索引。数组的等级是指维数的数量。数组的`Shape`是一个整数的元组,该元组给出数组在每个维度上的大小。
我们可以从Python列表中初始化NumPy数组,对于二维或更高维的数据使用嵌套列表。
例如
```
>>> a = np.array([1, 2, 3, 4, 5, 6])
```
或
```
>>> a = np.array([[1, 2, 3, 4], [5, 6, 7, 8], [9, 10, 11, 12]])
```
我们可以使用方括号访问数组中的元素。当你访问元素时,记住NumPy的索引是从0开始的。这意味着如果你想访问数组中的第一个元素,你将访问元素 "0"。
```
>>>print(a[0])
[1 2 3 4]
```
### 关于数组的更多信息
> 本节包括一维数组、二维数组、ndarray、向量、矩阵等。
您可能偶尔会听到称为“ndarray”的数组,它是“N 维数组”的简写。 N 维数组只是一个具有任意维数的数组。 您可能还会听到一维或一维数组、二维或二维数组等。 NumPy ndarray 类用于表示矩阵和向量。 向量是一维数组(行向量和列向量没有区别),而矩阵是二维数组。 对于 3-D 或更高维的阵列,术语张量也很常用。
数组通常是相同类型和大小的项目的固定大小容器。数组的中维数和项数由Shape定义。数组的size是一个指定每个维度大小的非负整数元组。
在NumPy中,维度被称作**axes**。例如,一个二维数组的表示如下所示:
```
[[0., 0., 0.],
[1., 1., 1.]]
```
那么这样的数组就有2个axes。第一个axes的长度为2,第二个axes的长度为3。
就像在其他Python容器对象中一样,数组的内容可以通过索引或切分数组来访问和修改。与典型的容器对象不同,不同的数组可以共享相同的数据,所以在一个数组上所做的改变可能在另一个数组中可见。
数组的属性反映了数组本身固有的信息。可以在不创建新数组的情况下获取甚至设置数组的属性,通常可以通过其属性访问数组。
### 创建一个简单的数组
本节包含 `np.array()`, `np.zeros()`, `np.ones()`, `np.empty()`, `np.arange()`, `np.linspace()`, `dtyp`
可以使用函数`np.array()`创建一个NumPy数组。
创建一个简单的数组所需要做的就是将一个列表传递给它。如果愿意,还可以在列表中制定数据类型。
```
>>> import numpy as np
>>> a = np.arrat([1,2,3])
```
![](https://numpy.org/doc/stable/_images/np_array.png)
请注意,这些可视化旨在简化想法并让您对 NumPy 概念和机制有一个基本的了解。数组和数组操作比这里捕获的要复杂得多!
除了从一系列元素创建数组外,您还可以轻松创建一个用 0 填充的数组:
```
>>>np.zeros(2)
array[0.,0.]
```
或者用1填充数组:
```
>>>np.ones(3)
array[1.,1.,1.]
```
或者甚至创建一个空数组。函数`emputy`可以创建一个数组,其初始内容是随机的并且取决于内存的状态。使用 empty over zeros(或类似的东西)的原因是速度 - 只需确保之后填充每个元素!
```
>>> # create an empty array with 2 elements
>>> np.empty(2)
array([3.14,42.])
```
你可以创建一个有元素范围的数组:
```
>>>np.arange(4)
arrray([0,1,2,3])
```
甚至还有一个包含一系列均匀间隔的数组。要做到这一点,你将指定第一个数字、最后一个数字和间隔大小。
```
>>>np.arange(1,10,2)
array([1,3,5,7,9])
```
你也可以使用np.linspace()来创建一个数组,该数组的值在指定的区间内呈线性间隔排列。
```
>>>np.linspace(0,10,num=5)
array([0.,2.5,5.,7.5,10.])
```
创建数组的默认数据类型是浮点型(np.float64),你可以通过`dtype`关键字指定创建数组的数据类型。
```
>>> x = np.ones(2,dtype=np.int64)
>>>x
array([1.1])
```
### 添加、移除、排序元素
> 本节包含 `np.sort()`, `np.concatenate()`
使用 `np.sort()`排序一个元素用是很简单的。可以在调用该函数时指定轴、种类和顺序。
如果你从这个数组开始:
```
>>> arr = np.array([2,1,3,4,8,6,7,5])
```
你可以以升序的方式对数组进行排序:
```
>>>np.sort(arr)
array([1,2,3,4,5,6,7,8])
```
除了sort(返回一个数组的排序副本)外,你还可以使用。
- argsort,这是一个沿着指定轴的间接排序。
- lexsort,这是对多个键的间接稳定排序。
- searchsorted,它将在一个已排序的数组中寻找元素,和
- partition,这是一个部分排序。
To read more about sorting an array, see: [`sort`](https://numpy.org/doc/stable/reference/generated/numpy.sort.html#numpy.sort).
如果你从这些数组开始:
```
>>> a = np.array([1,2,3,4])
>>> b = np.array([5,6,7,8])
```
你可以使用 `np.concatenate()`将他们连接。
```
>>> np.concateate((a,b))
array([1,2,3,4,5,6,7,8])
```
或者,从这些数组开始:
```
>>> x = np.array([1,2],[3,4])
>>> y = np.array([5,6])
```
你可以这样连接它们:
```
>>>np.concatenate((x,y) axis=0)
array([[1, 2],
[3, 4],
[5, 6]])
```
为了从一个数组中移除元素,很简单,使用索引来选择你想保留的元素。
### 数组的Shape(形状)和Size(大小)
> 本节包含ndarray.ndim`, `ndarray.size`, `ndarray.shape
- `ndarray.ndim` 表示数组的轴数或维数;
- `ndarray.size`表示数组中元素的总数,即数组的Shape的乘积。
- `ndarray.shape`表示一个整数元组,显示数组每个维度存储的元素数量。
例如:
```
>>>array_example = np.array([[[0, 1, 2, 3],
[4, 5, 6, 7]],
[[0, 1, 2, 3],
[4, 5, 6, 7]],
[[0 ,1 ,2, 3],
[4, 5, 6, 7]]])
```
```
# 共有3个轴
>>>array_example.ndim
3
```
```
# 共计24元素
>>>array_example.size
24
```
```
# 每个轴的长度分别为3、2、4
>>>array_example.shape
(3, 2, 4)
```
### 重塑数组
> 本节包含 `arr.reshape()`
使用 `arr.reshape()`可以在不改变数据的情况下产生一个新的`shape`。只要记住,当你使用reshape方法时,你想产生的数组需要有与原数组的相同元素数量。如果你从一个有12个元素的数组开始,你需要确保你的新数组也有总共12个元素。
```
>>> a = np.arrange(6)
>>> print(a)
[0 1 2 3 4 5 ]
```
你可以使用`reshape`方法重塑数组。例如,将上述的数组重塑为一个3行X2列的数组。
```
b = a.reshape(3,2)
>>> print(b)
[[0 1]
[2 3]
[4 5]]
```
在调用`np.reshape`方法时,可以指定几个可选参数,分别为`array`、`newshape`、`order:C`。
```
>>>np.reshape(a,newshape=(1,6),order = 'C')
```
- `a` 被重塑的数组
- `newshape` 新设定的`shape`,可以指定一个整数或一个整数元组。如果指定一个整数,那么结果是一个该长度的数组。`newshape`与原始`shape`兼容。
- `order` C 指的是使用类似C语言的索引顺序来读/写元素,F指的是使用类似Fortran语言的索引顺序。
### 一维数组转变为二维数组
> 本节包含`np.newaxis`, `np.expand_dims`
可以使用 `np.newaxis` 和`np.expand_dims` 来增加已有数组的维数。使用np.newaxis,当使用一次后,你的数组的维数将增加一维。这意味着一个一维数组将变成一个二维数组,一个二维数组将变成一个三维数组,以此类推。
```
>>>a = np.array([1,2,3,4,5,6])
>>>a.shape
(6,)
>>>print(a)
[1 2 3 4 5 6]
```
```
>>> a2 = a[np.newaxis,:]
>>> a2.shape
(1,6)
>>>print(a2)
[[1,2,3,4,5,6]]
```
你可以使用np.newaxis显式转换一个一维数组的行向量或列向量。例如,你可以通过沿第一维插入一个轴来将一个一维数组转换为行向量。
```
>>> row_vector = a[np.newaxis,:]
>>> row_vector.shape
(1,6)
>>>print(col_vector)
```
或者,对于一个列向量,你可以沿第二维插入一个轴。
```
>>> col_vector = a[:,np.newaxis]
>>>col_vector.shape
(6,1)
>>>print(col_vector)
[[1]
[2]
[3]
[4]
[5]
[6]]
```
你也可以用np.expand_dims在指定的位置插入一个新轴来扩展一个数组。
```
>>> a = np.array([1,2,3,4,5,6])
>>> a.shape
(6,)
```
你可以用np.expand_dims在索引位置1处添加一个轴:
```
>>> b = np.expand_dims(a,axis=1)
>>> b.shape
(6,1)
>>> print(b)
[[1]
[2]
[3]
[4]
[5]
[6]]
```
也可以用np.expand_dims在索引位置0处添加一个轴:
```
>>> c = np.expand_dims(a,axis=0)
>>> c.shape
(1,6)
>>> print(c)
[[1 2 3 4 5 6]]
```
NumPy初学者教程