更新了数据分析部分的文档

pull/724/head
jackfrued 2020-12-20 22:01:06 +08:00
parent 84fe683c6d
commit 8c4e7d2bf1
6 changed files with 765 additions and 29 deletions

View File

@ -111,13 +111,19 @@
对于安装了Python环境但是没有安装Anaconda的用户可以用Python的包管理工具pip来安装`jupyter`然后在终端Windows系统称之为命令行提示符中运行`jupyter notebook`命令来启动Notebook如下所示。
安装:
安装Notebook
```Bash
pip install jupyter
```
运行:
安装三大神器:
```Bash
pip install numpy pandas matplotlib
```
运行Notebook
```Bash
jupyter notebook
@ -234,7 +240,7 @@ Notebook是基于网页的用于交互计算的应用程序可以用于代码
**第一四分位数**$Q_1$),又称**较小四分位数**或**下四分位数**等于该样本中所有数值由小到大排列后第25%的数字。
**第二四分位数**$Q_2$又称**中位数**等于该样本中所有数值由小到大排列后第50%的数字。
**第二四分位数**$Q_2$**中位数**等于该样本中所有数值由小到大排列后第50%的数字。
**第三四分位数**$Q_3$),又称**较大四分位数**或**上四分位数**等于该样本中所有数值由小到大排列后第75%的数字。

View File

@ -1,59 +1,789 @@
## NumPy的应用
Numpy是一个开源的Python科学计算库**用于快速处理任意维度的数组**。Numpy**支持常见的数组和矩阵操作**对于同样的数值计算任务使用NumPy不仅代码要简洁的多而且NumPy的性能远远优于原生Python基本是1个到2个数量级的差距而且数据量越大NumPy的优势就越明显。
Numpy是一个开源的Python科学计算库**用于快速处理任意维度的数组**。Numpy**支持常见的数组和矩阵操作**对于同样的数值计算任务使用NumPy不仅代码要简洁的多而且NumPy的性能远远优于原生Python基本是一个到两个数量级的差距而且数据量越大NumPy的优势就越明显。
Numpy最为核心的数据类型是`ndarray`,使用`ndarray`可以处理一维、二维和多维数组该对象相当于是一个快速而灵活的大数据容器。NumPy底层代码使用C语言编写解决了GIL的限制`ndarray`在存储数据的时候数据与数据的地址都是连续的这样就给使得批量操作速度很快远远优于Python中的`list`;另一方面`ndarray`对象提供了更多的方法来处理数据尤其是和统计相关的方法这些方法也是Python原生的`list`没有的。
### 安装和导入NumPy
### 准备工作
1. 安装
1. 启动Notebook
```Bash
pip install numpy
jupyter notebook
```
> **提示**在启动Notebook之前建议先安装好数据分析相关依赖项包括之前提到的三大神器以及相关依赖项包括`numpy`、`pandas`、`matplotlib`、`openpyxl`、`xlrd`、`xlwt`等。如果使用Anaconda则无需单独安装。
2. 导入
```Python
import numpy as np
import pandas as pd
import matplotlib.pyplot as plt
```
> **说明**如果已经启动了Notebook但尚未安装NumPy可以在单元格中输入`!pip install numpy `并运行该单元格来安装NumPy安装成功后记得重启Notebook内核来使新安装的库生效
> **说明**如果已经启动了Notebook但尚未安装相关依赖库例如NumPy可以在Notebook的单元格中输入`!pip install numpy`并运行该单元格来安装NumPy其他库如法炮制。安装成功后选择“Kernel”服务菜单的“Restart”重启选项来重启Notebook内核前面有讲到重启的快捷键来使新安装的库生效。上面我们不仅导入了NumPy还将pandas和matplotlib库一并导入了
### 创建数组对象
1. 一维数组
- 方法一使用array函数通过list创建数组对象
- 方法二使用arange函数指定取值范围创建数组对象
- 方法三使用linspace函数用指定范围均匀间隔的数字创建数组对象
- 方法四使用numpy.random模块的函数生成随机数创建数组对象
2. 二维数组
- 方法一使用array函数通过嵌套的list创建数组对象
- 方法二使用zeros、ones、full函数指定数组的形状创建数组对象
- 方法三使用eye函数创建单位矩阵
- 方法四通过reshape将一维数组变成二维数组
- 方法五通过numpy.random模块的函数生成随机数创建数组对象
3. 多维数组:跟上面的情况相似,可以通过下面的例子进行了解。
创建`ndarray`对象有很多种方法,下面就如何创建一维数组、二维数组和多维数组进行说明。
#### 一维数组
- 方法一:使用`array`函数,通过`list`创建数组对象
代码:
```Python
array1 = np.array([1, 2, 3, 4, 5])
array1
```
输出:
```
array([1, 2, 3, 4, 5])
```
- 方法二:使用`arange`函数,指定取值范围创建数组对象
代码:
```Python
array2 = np.arange(0, 20, 2)
array2
```
输出:
```
array([ 0, 2, 4, 6, 8, 10, 12, 14, 16, 18])
```
- 方法三:使用`linspace`函数,用指定范围均匀间隔的数字创建数组对象
代码:
```Python
array3 = np.linspace(-5, 5, 101)
array3
```
输出:
```
array([-5. , -4.9, -4.8, -4.7, -4.6, -4.5, -4.4, -4.3, -4.2, -4.1, -4. ,
-3.9, -3.8, -3.7, -3.6, -3.5, -3.4, -3.3, -3.2, -3.1, -3. , -2.9,
-2.8, -2.7, -2.6, -2.5, -2.4, -2.3, -2.2, -2.1, -2. , -1.9, -1.8,
-1.7, -1.6, -1.5, -1.4, -1.3, -1.2, -1.1, -1. , -0.9, -0.8, -0.7,
-0.6, -0.5, -0.4, -0.3, -0.2, -0.1, 0. , 0.1, 0.2, 0.3, 0.4,
0.5, 0.6, 0.7, 0.8, 0.9, 1. , 1.1, 1.2, 1.3, 1.4, 1.5,
1.6, 1.7, 1.8, 1.9, 2. , 2.1, 2.2, 2.3, 2.4, 2.5, 2.6,
2.7, 2.8, 2.9, 3. , 3.1, 3.2, 3.3, 3.4, 3.5, 3.6, 3.7,
3.8, 3.9, 4. , 4.1, 4.2, 4.3, 4.4, 4.5, 4.6, 4.7, 4.8,
4.9, 5. ])
```
- 方法四:使用`numpy.random`模块的函数生成随机数创建数组对象
产生10个$[0, 1)$范围的随机小数,代码:
```Python
array4 = np.random.rand(10)
array4
```
输出:
```
array([0.45556132, 0.67871326, 0.4552213 , 0.96671509, 0.44086463,
0.72650875, 0.79877188, 0.12153022, 0.24762739, 0.6669852 ])
```
产生10个$[1, 100)$范围的随机整数,代码:
```Python
array5 = np.random.randint(1, 101, 10)
array5
```
输出:
```
array([29, 97, 87, 47, 39, 19, 71, 32, 79, 34])
```
产生20个$\mu=50$$\sigma=10$的正态分布随机数,代码:
```Python
array6 = np.random.normal(50, 10, 20)
array6
```
输出:
```
array([55.04155586, 46.43510797, 20.28371158, 62.67884053, 61.23185964,
38.22682148, 53.17126151, 43.54741592, 36.11268017, 40.94086676,
63.27911699, 46.92688903, 37.1593374 , 67.06525656, 67.47269463,
23.37925889, 31.45312239, 48.34532466, 55.09180924, 47.95702787])
```
#### 二维数组
- 方法一:使用`array`函数,通过嵌套的`list`创建数组对象
代码:
```Python
array7 = np.array([[1, 2, 3], [4, 5, 6]])
array7
```
输出:
```
array([[1, 2, 3],
[4, 5, 6]])
```
- 方法二:使用`zeros`、`ones`、`full`函数指定数组的形状创建数组对象
使用`zeros`函数,代码:
```Python
array8 = np.zeros((3, 4))
array8
```
输出:
```
array([[0., 0., 0., 0.],
[0., 0., 0., 0.],
[0., 0., 0., 0.]])
```
使用`ones`函数,代码:
```Python
array9 = np.ones((3, 4))
array9
```
输出:
```
array([[1., 1., 1., 1.],
[1., 1., 1., 1.],
[1., 1., 1., 1.]])
```
使用`full`函数,代码:
```Python
array10 = np.full((3, 4), 10)
array10
```
输出:
```
array([[10, 10, 10, 10],
[10, 10, 10, 10],
[10, 10, 10, 10]])
```
- 方法三使用eye函数创建单位矩阵
代码:
```Python
array11 = np.eye(4)
array11
```
输出:
```
array([[1., 0., 0., 0.],
[0., 1., 0., 0.],
[0., 0., 1., 0.],
[0., 0., 0., 1.]])
```
- 方法四:通过`reshape`将一维数组变成二维数组
代码:
```Python
array12 = np.array([1, 2, 3, 4, 5, 6]).reshape(2, 3)
array12
```
输出:
```
array([[1, 2, 3],
[4, 5, 6]])
```
> **提示**`reshape`是`ndarray`对象的一个方法,使用`reshape`方法时需要确保调形后的数组元素个数与调形前数组元素个数保持一致,否则将会产生异常。
- 方法五:通过`numpy.random`模块的函数生成随机数创建数组对象
产生$[0, 1)$范围的随机小数构成的3行4列的二维数组代码
```Python
array13 = np.random.rand(3, 4)
array13
```
输出:
```
array([[0.54017809, 0.46797771, 0.78291445, 0.79501326],
[0.93973783, 0.21434806, 0.03592874, 0.88838892],
[0.84130479, 0.3566601 , 0.99935473, 0.26353598]])
```
产生$[1, 100)$范围的随机整数构成的3行4列的二维数组代码
```Python
array14 = np.random.randint(1, 100, (3, 4))
array14
```
输出:
```
array([[83, 30, 64, 53],
[39, 92, 53, 43],
[43, 48, 91, 72]])
```
#### 多维数组
- 使用随机的方式创建多维数组
代码:
```Python
array15 = np.random.randint(1, 100, (3, 4, 5))
array15
```
输出:
```
array([[[94, 26, 49, 24, 43],
[27, 27, 33, 98, 33],
[13, 73, 6, 1, 77],
[54, 32, 51, 86, 59]],
[[62, 75, 62, 29, 87],
[90, 26, 6, 79, 41],
[31, 15, 32, 56, 64],
[37, 84, 61, 71, 71]],
[[45, 24, 78, 77, 41],
[75, 37, 4, 74, 93],
[ 1, 36, 36, 60, 43],
[23, 84, 44, 89, 79]]])
```
- 将一维二维的数组调形为多维数组
一维数组调形为多维数组,代码:
```Python
array16 = np.arange(1, 25).reshape((2, 3, 4))
array16
```
输出:
```Python
array([[[ 1, 2, 3, 4],
[ 5, 6, 7, 8],
[ 9, 10, 11, 12]],
[[13, 14, 15, 16],
[17, 18, 19, 20],
[21, 22, 23, 24]]])
```
二维数组调形为多维数组,代码:
```Python
array17 = np.random.randint(1, 100, (4, 6)).reshape((4, 3, 2))
array17
```
输出:
```
array([[[60, 59],
[31, 80],
[54, 91]],
[[67, 4],
[ 4, 59],
[47, 49]],
[[16, 4],
[ 5, 71],
[80, 53]],
[[38, 49],
[70, 5],
[76, 80]]])
```
- 读取图片获得对应的三维数组
代码:
```Python
array18 = plt.imread('guido.jpg')
array18
```
输出:
```
array([[[ 36, 33, 28],
[ 36, 33, 28],
[ 36, 33, 28],
...,
[ 32, 31, 29],
[ 32, 31, 27],
[ 31, 32, 26]],
[[ 37, 34, 29],
[ 38, 35, 30],
[ 38, 35, 30],
...,
[ 31, 30, 28],
[ 31, 30, 26],
[ 30, 31, 25]],
[[ 38, 35, 30],
[ 38, 35, 30],
[ 38, 35, 30],
...,
[ 30, 29, 27],
[ 30, 29, 25],
[ 29, 30, 25]],
...,
[[239, 178, 123],
[237, 176, 121],
[235, 174, 119],
...,
[ 78, 68, 56],
[ 75, 67, 54],
[ 73, 65, 52]],
[[238, 177, 120],
[236, 175, 118],
[234, 173, 116],
...,
[ 82, 70, 58],
[ 78, 68, 56],
[ 75, 66, 51]],
[[238, 176, 119],
[236, 175, 118],
[234, 173, 116],
...,
[ 84, 70, 61],
[ 81, 69, 57],
[ 79, 67, 53]]], dtype=uint8)
```
> **说明**:上面的代码读取了当前路径下名为`guido.jpg` 的图片文件计算机系统中的图片通常由若干行若干列的像素点构成而每个像素点又是由红绿蓝三原色构成的所以能够用三维数组来表示。读取图片用到了matplotlib库的`imread`函数。
### 数组对象的属性
1. size属性数组元素个数
2. itemsize属性数组单个元素占用内存空间的字节数
3. shape属性数组的形状
4. dtype属性数组元素的数据类型
5. ndim属性数组的维度
6. flat属性数组一维化之后元素的迭代器
7. nbytes属性数组所有元素占用内存空间的字节数
1. `size`属性:数组元素个数
代码:
```Python
array19 = np.arange(1, 100, 2)
array20 = np.random.rand(3, 4)
print(array19.size, array20.size)
```
输出:
```
50 12
```
2. `shape`属性:数组的形状
代码:
```Python
print(array19.shape, array20.shape)
```
输出:
```
(50,) (3, 4)
```
3. `dtype`属性:数组元素的数据类型
代码:
```Python
print(array19.dtype, array20.dtype)
```
输出:
```
int64 float64
```
`ndarray`对象元素的数据类型可以参考如下所示的表格。
![](res/ndarray-dtype.png)
4. `ndim`属性:数组的维度
代码:
```Python
print(array19.ndim, array20.ndim)
```
输出:
```
1 2
```
5. `itemsize`属性:数组单个元素占用内存空间的字节数
代码:
```Python
array21 = np.arange(1, 100, 2, dtype=np.int8)
print(array19.itemsize, array20.itemsize, array21.itemsize)
```
输出:
```
8 8 1
```
> **说明**:在使用`arange`创建数组对象时,通过`dtype`参数指定元素的数据类型。可以看出,`np.int8`代表的是8位有符号整数只占用1个字节的内存空间取值范围是$[-128,127]$。
6. `nbytes`属性:数组所有元素占用内存空间的字节数
代码:
```Python
print(array19.nbytes, array20.nbytes, array21.nbytes)
```
输出:
```
400 96 50
```
7. `flat`属性:数组(一维化之后)元素的迭代器
代码:
```Python
from typing import Iterable
print(isinstance(array20.flat, np.ndarray), isinstance(array20.flat, Iterable))
```
输出:
```
False True
```
8. base属性数组的基对象如果数组共享了其他数组的内存空间
代码:
```Python
array22 = array19[:]
print(array22.base is array19, array22.base is array21)
```
输出:
```
True False
```
> **说明**上面的代码用到了数组的切片操作它类似于Python中`list`类型的切片,但在细节上又不完全相同,下面会专门讲解这个知识点。通过上面的代码可以发现,`ndarray`切片后得到的新的数组对象跟原来的数组对象共享了内存中的数据,因此`array22`的`base`属性就是`array19`对应的数组对象。
### 数组的索引和切片
和Python中的列表类似NumPy的`ndarray`对象可以进行索引和切片操作,通过索引可以获取或修改数组中的元素,通过切片可以取出数组的一部分。
1. 索引运算
一维数组,代码:
```Python
array23 = np.array([1, 2, 3, 4, 5, 6, 7, 8, 9])
print(array23[0], array23[array23.size - 1])
print(array23[-array23.size], array23[-1])
```
输出:
```
1 9
1 9
```
二维数组,代码:
```Python
array24 = np.array([[1, 2, 3], [4, 5, 6], [7, 8, 9]])
print(array24[2])
print(array24[0][0], array24[-1][-1])
print(array24[1][1], array24[1, 1])
```
输出:
```
[7 8 9]
1 9
5 5
[[ 1 2 3]
[ 4 10 6]
[ 7 8 9]]
```
代码:
```Python
array24[1][1] = 10
print(array24)
array24[1] = [10, 11, 12]
print(array24)
```
输出:
```
[[ 1 2 3]
[ 4 10 6]
[ 7 8 9]]
[[ 1 2 3]
[10 11 12]
[ 7 8 9]]
```
2. 切片运算
代码:
```Python
print(array24[:2, 1:])
```
输出:
```
[[2 3]
[5 6]]
```
代码:
```Python
print(array24[2])
print(array24[2, :])
```
输出:
```
[7 8 9]
[7 8 9]
```
代码:
```Python
print(array24[2:, :])
```
输出:
```
[[7 8 9]]
```
代码:
```Python
print(array24[:, :2])
```
输出:
```
[[1 2]
[4 5]
[7 8]]
```
代码:
```Python
print(array24[1, :2])
```
输出:
```
[4 5]
```
代码:
```Python
print(array24[1:2, :2])
```
输出:
```
[[4 5]]
```
关于数组的索引和切片运算,大家可以通过下面的两张图来增强印象,这两张图来自[《利用Python进行数据分析》](https://item.jd.com/12398725.html)一书它是pandas的作者Wes McKinney撰写的Python数据分析领域的经典教科书有兴趣的读者可以购买和阅读原书。
![](res/ndarray-index.png)
![](res/ndarray-slice.png)
### 数组对象的方法
#### 常用方法
#### 统计方法
`ndarray`对象的统计方法主要包括:`sum`、`mean`、`std`、`var`、`min`、`max`、`argmin`、`argmax`、`cumsum`等,分别用于对数组中的元素求和、求平均、求标准差、求方差、找最大、找最小、求累积和等,请参考下面的代码。
```Python
array25 = np.array([1, 2, 3, 4, 5, 5, 4, 3, 2, 1])
print(array25.sum())
print(array25.mean())
print(array25.max())
print(array25.min())
print(array25.std())
print(array25.var())
print(array25.cumsum())
```
输出:
```
30
3.0
5
1
1.4142135623730951
2.0
[ 1 3 6 10 15 20 24 27 29 30]
```
####其他方法
1. `all()` / `any()`方法判断数组是否所有元素都是True / 判断数组是否有为True的元素。
2. `astype()`方法:拷贝数组,并将数组中的元素转换为指定的类型。
3. `dot()`方法:实现一个数组和另一个数组的点乘运算。
```Python
```
输出:
```
```
4. `dump()`/`load()`方法:保存数组到文件中/从文件中加载数组。
```Python
```
输出:
```
```
5. `fill()`方法。
```Python
```
输出:
```
```
6. `flatten()`方法:将多维数组扁平化为一维数组。
```Python
```
输出:
```
```
7. `nonzero()`方法返回非0元素的索引。
8. `round()`方法:对数组中的元素做四舍五入操作。
9. `sort()`方法:对数组进行就地排序。
```Python
```
输出:
```
```
10. `swapaxes()`和`transpose()`方法:交换数组指定的轴
11. `take()`方法:从数组中取指定索引的元素。
12. `tolist()`方法将数组转成Python中的`list`。
### 数组的运算
#### 标量运算

View File

Before

Width:  |  Height:  |  Size: 127 KiB

After

Width:  |  Height:  |  Size: 127 KiB

View File

Before

Width:  |  Height:  |  Size: 236 KiB

After

Width:  |  Height:  |  Size: 236 KiB

View File

Before

Width:  |  Height:  |  Size: 61 KiB

After

Width:  |  Height:  |  Size: 61 KiB

View File

Before

Width:  |  Height:  |  Size: 92 KiB

After

Width:  |  Height:  |  Size: 92 KiB