Skip to content

Commit

Permalink
更新了数据分析部分的文档和代码
Browse files Browse the repository at this point in the history
  • Loading branch information
jackfrued committed Dec 23, 2020
1 parent 5ce64ba commit a7b48eb
Show file tree
Hide file tree
Showing 3 changed files with 1,062 additions and 22 deletions.
205 changes: 183 additions & 22 deletions Day66-70/67.NumPy的应用.md
Original file line number Diff line number Diff line change
Expand Up @@ -129,6 +129,8 @@ Numpy最为核心的数据类型是`ndarray`,使用`ndarray`可以处理一维
23.37925889, 31.45312239, 48.34532466, 55.09180924, 47.95702787])
```

> **说明**:创建一维数组还有很多其他的方式,比如通过读取字符串、读取文件、解析正则表达式等方式,这里我们暂不讨论这些方式,有兴趣的读者可以自行研究。

#### 二维数组

- 方法一:使用`array`函数,通过嵌套的`list`创建数组对象
Expand Down Expand Up @@ -1021,7 +1023,7 @@ print(array28.cumsum())
### 数组的运算
使用NumPy最为方便的是当需要对数组元素进行运算时,不用编写循环代码遍历每个元素,所有的运算都会自动的矢量化(使用高效的提前编译的底层语言代码来对数据序列进行数学操作)。简单的说就是,NumPy中的数学运算和数学函数会自动作用于数组中的每个成员。
使用NumPy最为方便的是当需要对数组元素进行运算时,不用编写循环代码遍历每个元素,所有的运算都会自动的**矢量化**(使用高效的提前编译的底层语言代码来对数据序列进行数学操作)。简单的说就是,NumPy中的数学运算和数学函数会自动作用于数组中的每个成员。
#### 数组跟标量的运算
Expand Down Expand Up @@ -1122,11 +1124,22 @@ print(np.power(array37, array38))
| 函数 | 说明 |
| --------------------------------- | ---- |
| `add` / `substract` / `multiply` | 加法函数 / 减法函数 / 乘法函数 |
| `divide` / `floor_divide` / `mod` | 除法函数 / 整除函数 / 求模函数 |
| `power` | 数组$A$的元素$A_i$和数组$B$的元素$B_i$,计算$A_i^{B_i}$ |
| `maximum` / `fmax` | 获取最大值 / 获取最大值,忽略NaN |
| `minimum` / `fmin` | 获取最小值 / 获取最小值,忽略NaN |
| `add(x, y)` / `substract(x, y)` / `multiply` | 加法函数 / 减法函数 |
|`multiply(x, y)` / `divide(x, y)`|乘法函数 / 除法函数|
| `floor_divide(x, y)` / `mod(x, y)` | 整除函数 / 求模函数 |
|`allclose(x, y)`|检查数组`x``y`元素是否几乎相等|
| `power(x, y)` | 数组$x$的元素$x_i$和数组$y$的元素$y_i$,计算$x_i^{y_i}$ |
| `maximum(x, y)` / `fmax(x, y)` | 两两比较元素获取最大值 / 获取最大值(忽略NaN) |
| `minimum(x, y)` / `fmin(x, y)` | 两两比较元素获取最小值 / 获取最小值(忽略NaN) |
| `inner(x, y)` | 内积运算 |
| `cross(x, y) `/ `outer(x, y)` | 叉积运算 / 外积运算 |
| `intersect1d(x, y)` | 计算`x``y`的交集,返回这些元素构成的有序数组 |
| `union1d(x, y)` | 计算`x``y`的并集,返回这些元素构成的有序数组 |
| `in1d(x, y)` | 返回由判断`x` 的元素是否在`y`中得到的布尔值构成的数组 |
| `setdiff1d(x, y)` | 计算`x``y`的差集,返回这些元素构成的数组 |
| `setxor1d(x, y)` | 计算`x``y`的对称差,返回这些元素构成的数组 |
>**补充说明:在二维空间内,两个向量$\boldsymbol{A}=\begin{bmatrix} a_1 \\ a_2 \end{bmatrix}$和$\boldsymbol{B}=\begin{bmatrix} b_1 \\ b_2 \end{bmatrix}$的叉积是这样定义的:$\boldsymbol{A}\times \boldsymbol{B}=\begin{vmatrix} a_1 \quad a_2 \\ b_1 \quad b_2 \end{vmatrix}=a_1b_2 - a_2b_1$,其中$\begin{vmatrix} a_1 \quad a_2 \\ b_1 \quad b_2 \end{vmatrix}$称为行列式。但是一定要注意,叉积并不等同于行列式,行列式的运算结果是一个标量,而叉积运算的结果是一个向量。如果不明白,我们可以看看三维空间两个向量,$\boldsymbol{A}=\begin{bmatrix} a_1 \\ a_2 \\ a_3 \end{bmatrix}$和$\boldsymbol{B}=\begin{bmatrix} b_1 \\ b_2 \\ b_3 \end{bmatrix}$的叉积是$\left< \hat{i} \begin{vmatrix} a_2 \quad a_3 \\ b_2 \quad b_3 \end{vmatrix}, -\hat{j} \begin{vmatrix} a_1 \quad a_3 \\ b_1 \quad b_3 \end{vmatrix}, \hat{k} \begin{vmatrix} a_1 \quad a_2 \\ b_1 \quad b_2 \end{vmatrix} \right>$,其中$\hat{i}, \hat{j}, \hat{k}$代表每个维度的单位向量。
#### 广播机制
Expand Down Expand Up @@ -1179,19 +1192,29 @@ array([[1, 1, 1],
**表3:NumPy其他常用函数**
| 函数 | 说明 |
| ------------------- | ----------------------------------------------------- |
| `unique(x)` | 去除数组`x`重复元素,返回唯一元素构成的有序数组 |
| `intersect1d(x, y)` | 计算`x``y`的交集,返回这些元素构成的有序数组 |
| `union1d(x, y)` | 计算`x``y`的并集,返回这些元素构成的有序数组 |
| `in1d(x, y)` | 返回由判断`x` 的元素是否在`y`中得到的布尔值构成的数组 |
| `setdiff1d(x, y)` | 计算`x``y`的差集,返回这些元素构成的数组 |
| `setxor1d(x, y)` | 计算`x``y`的对称差,返回这些元素构成的数组 |
| `copy(x)` | 返回拷贝数组`x`得到的数组 |
| `sort(x)` | 返回数组`x`元素排序后的拷贝 |
| `split(x)` | 将数组`x`拆成若干个子数组 |
| `hstack` / `vstack` | 将多个数组水平/垂直堆叠构成新数组 |
| `concatenate` | 沿着指定的轴连接多个数组构成新数组 |
| 函数 | 说明 |
| ------------------- | ------------------------------------------------ |
| `unique` | 去除数组重复元素,返回唯一元素构成的有序数组 |
| `copy` | 返回拷贝数组得到的数组 |
| `sort` | 返回数组元素排序后的拷贝 |
| `split` / `hsplit` / `vsplit` | 将数组拆成若干个子数组 |
| `stack` / `hstack` / `vstack` | 将多个数组堆叠成新数组 |
| `concatenate` | 沿着指定的轴连接多个数组构成新数组 |
| `append` / `insert` | 向数组末尾追加元素 / 在数组指定位置插入元素 |
| `argwhere` | 找出数组中非0元素的位置 |
| `extract` / `select` / `where` | 按照指定的条件从数组中抽取或处理数组元素 |
| `flip` | 沿指定的轴翻转数组中的元素 |
| `fromiter` | 通过迭代器创建数组对象 |
| `fromregex` | 通过读取文件和正则表达式解析获取数据创建数组对象 |
| `repeat` / `tile` | 通过对元素的重复来创建新数组 |
| `roll` | 沿指定轴对数组元素进行移位 |
| `resize` | 重新调整数组的大小 |
| `place` / `put` | 将数组中满足条件的元素/指定的元素替换为指定的值 |
| `ptp` | 沿指定的轴计算极差(最大值与最小值的差) |
| `median` | 沿指定轴计算中位数 |
| `partition` | 用选定的元素对数组进行一次划分并返回划分后的数组 |
> **提示**:上面的`resize`函数和`ndarray`对象的`resize`方法是有区别的,`resize`函数在调整数组大小时会重复数组中的元素作为填补多出来的元素的值,而`ndarry`对象的`resize`方法是用0来填补多出来的元素。这些小细节不清楚暂时也不要紧,但是如果用到对应的功能了就要引起注意。
代码:
Expand Down Expand Up @@ -1259,11 +1282,149 @@ array([[1, 1, 1, 4, 4, 4],
### 矩阵运算
我们可以用二维数组表示数学上的矩阵,NumPy中也提供了专门用于矩阵运算的模块和函数。
NumPy中提供了专门用于线性代数(linear algebra)的模块和表示矩阵的类型`matrix`,当然我们通过二维数组也可以表示一个矩阵,官方并不推荐使用`matrix`类而是建议使用二维数组,而且有可能在将来的版本中会移除`matrix`类。无论如何,利用这些已经封装好的类和函数,我们可以轻松愉快的实现线性代数中很多的操作。
#### 线性代数快速回顾
1. **向量**也叫**矢量**,是一个同时具有大小和方向,且满足平行四边形法则的几何对象。与向量相对的概念叫**标量**或**数量**,标量只有大小、绝大多数情况下没有方向。
2. 向量可以进行**加**、**减**、**数乘**、**点积**、**叉积**等运算。
3. **行列式**由向量组成,它的性质可以由向量解释。
4. 行列式可以使用**行列式公式**计算:$det(\boldsymbol{A})=\sum_{n!} \pm {a_{1\alpha}a_{2\beta} \cdots a_{n\omega}}$。
5. 高阶行列式可以用**代数余子式**展开成多个低阶行列式,如:$det(\boldsymbol{A})=a_{11}C_{11}+a_{12}C_{12}+ \cdots +a_{1n}C_{1n}$。
6. **矩阵**是由一系列元素排成的矩形阵列,矩阵里的元素可以是数字、符号或数学公式。
7. 矩阵可以进行**加法**、**减法**、**数乘**、**乘法**、**转置**等运算。
8. **逆矩阵**用$\boldsymbol{A^{-1}}$表示,$\boldsymbol{A}\boldsymbol{A^{-1}}=\boldsymbol{A^{-1}}\boldsymbol{A}=\boldsymbol{I}$;没有逆矩阵的方阵是**奇异矩阵**。
9. 如果一个方阵是**满秩矩阵**,该方阵对应的线性方程有唯一解。
#### NumPy中矩阵相关函数
1. 创建矩阵对象。
代码:
```Python
# matrix构造函数可以传入类数组对象也可以传入字符串
m1 = np.matrix('1 2 3; 4 5 6')
m1
```
输出:
```
matrix([[1, 2, 3],
[4, 5, 6]])
```
代码:
```Python
# asmatrix函数也可以写成mat函数,它们其实是同一个函数
m2 = np.asmatrix(np.array([[1, 1], [2, 2], [3, 3]]))
m2
```
输出:
```
matrix([[1, 1],
[2, 2],
[3, 3]])
```
代码:
```Python
# 矩阵乘法运算,等同于m1.dot(m2)
m1 * m2
```
输出:
```
matrix([[14, 14],
[32, 32]])
```
2. 矩阵对象的属性。
| 属性 | 说明 |
| ------- | ----------------------------------------- |
| `A` | 获取矩阵对象对应的`ndarray`对象 |
| `A1` | 获取矩阵对象对应的扁平化后的`ndarray`对象 |
| `I` | 可逆矩阵的逆矩阵 |
| `T` | 矩阵的转置 |
| `H` | 矩阵的共轭转置 |
| `shape` | 矩阵的形状 |
| `size` | 矩阵元素的个数 |
3. 矩阵对象的方法。
#### 线性代数回顾
矩阵对象的方法跟之前讲过的`ndarray`数组对象的方法基本差不多,此处不再进行赘述。
#### NumPy的线性代数模块
NumPy的`linalg`模块中有一组标准的矩阵分解运算以及诸如求逆和行列式之类的函数,它们跟MATLAB和R等语言所使用的是相同的行业标准线性代数库,下面的表格列出了`numpy`以及`linalg`模块中常用的跟线性代数相关的函数。
#### 线性代数模块
| 函数 | 说明 |
| --------------- | ------------------------------------------------------------ |
| `diag` | 以一维数组的形式返回方阵的对角线元素或将一维数组转换为方阵(非对角元素元素为0) |
| `vdot` | 向量的点积 |
| `dot` | 数组的点积(矩阵乘法) |
| `inner` | 数组的内积 |
| `outer` | 数组的叉积 |
| `trace` | 计算对角线元素的和 |
| `norm` | 求模运算 |
| `det` | 计算行列式的值(在方阵上计算得到的标量) |
| `matrix_rank` | 计算矩阵的秩 |
| `eig` | 计算矩阵的特征值(eigenvalue)和特征向量(eigenvector) |
| `inv` | 计算非奇异矩阵($n$阶方阵)的逆矩阵 |
| `pinv` | 计算矩阵的摩尔-彭若斯(Moore-Penrose)广义逆 |
| `qr` | QR分解(把矩阵分解成一个正交矩阵与一个上三角矩阵的积) |
| `svd` | 计算奇异值分解(singular value decomposition) |
| `solve` | 解线性方程组$\boldsymbol{A}\boldsymbol{x}=\boldsymbol{b}$,其中$\boldsymbol{A}$是一个方阵 |
| `lstsq` | 计算$\boldsymbol{A}\boldsymbol{x}=\boldsymbol{b}$的最小二乘解 |
大家如果有兴趣可以用下面的代码验证上面的函数。
代码:
```Python
m3 = np.array([[1., 2.], [3., 4.]])
np.linalg.inv(m3)
```
输出:
```
array([[-2. , 1. ],
[ 1.5, -0.5]])
```
代码:
```Python
m4 = np.array([[1, 3, 5], [2, 4, 6], [4, 7, 9]])
np.linalg.det(m4)
```
输出:
```
2
```
代码:
```Python
# 解线性方程组ax=b
# 3x + y = 9,x + 2y = 8
a = np.array([[3,1], [1,2]])
b = np.array([9, 8])
np.linalg.solve(a, b)
```
输出:
```
array([2., 3.])
```
Loading

0 comments on commit a7b48eb

Please sign in to comment.