master
aolingwen 6 years ago
commit 9233129026

@ -0,0 +1,57 @@
# 1.1.1HelloPython
## Python为何物
说出来您可能不信,现在大名鼎鼎的编程语言 Python 是由 Guido van Rossum 在 1989 年圣诞节期间,为了打发无聊的圣诞节而编写的一个编程语言。而也正是因为作者的无聊,我们现在才得以使用风靡全球的编程语言 Python 。(无聊是个好东西)
Python 为什么这么流行呢?主要原因有两个:
- 首先是因为本身语法简单而且提供了非常完善的基础代码库覆盖了如网络、文件、GUI、数据库、正则表达式等大量内容。您可别小看了这些基础代码库它会让我们在实现功能时减少我们的代码量将我们从底层代码中解放出来更加的关心我们需要实现的业务功能。
- 其次是大家觉得 Python 这么好用,就会有很多具有开源精神的开发者去开发各种各样的第三方模块。接着大家可能会去尝试使用这些模块,然后发现这些模块挺好用的,然后就可能会把这些好用的模块或者 Python 语言推荐给自己的朋友、同事。就这样,不断地完善了 Python 的生态。以前用 C 语言想要实现一个功能可能需要 30 行代码,而用 Python 可能只需要 1 行代码。这也就使得编程的门槛越来越低,越来越流行。
事物都有两面性,既然 Python 有这么大的优点,那肯定也有不小的缺点。 Python 最为致命的确定就是运行速度慢。由于 Python 是解释型语言,您所编写的代码在执行时,解释器会一行一行的翻译成 CPU 能理解的机器码,这个翻译过程是非常耗时的,所以 Python 的运行速度很慢。而像 C 语言所编写的程序在运行前会直接将代码翻译成 CPU 能够理解的机器码,所以 C 语言编写的程序运行时非常快。
不过值得庆幸的是,大量的应用程序不需要这么快的运行速度,因为用户根本感觉不出来。例如开发一个下载 短视频 的网络应用程序C 程序的运行时间需要0.001 秒,而 Python 程序的运行时间需要 0.1 秒,慢了 100 倍,但由于网络更慢,需要等待 5 秒。您可以思考一下,用户真的能感觉到 5.001 秒和 5.1秒 的区别吗?
这就好比布加迪威龙和五菱宏光在北京三环路上行驶的道理一样,虽然理论时速高达 430 公里,但由于三环路堵车的时速只有 20 公里,因此,作为乘客,您感觉的时速是 20 公里。
所以选择 Python 作为编程语言是一种比较明智的选额。
## 如何安装Python
相信现在您可能已经迫不及待地想要在自己的机器上安装 Python 并开始 Python 之旅了。不过在安装 Python 前还需要了解一个知识,就是 Python 其实有两个不兼容的版本,一个是 2.x 版,另一个是 3.x 版。但由于 2.x 版只维护到 2020 年,而且 Python 官方都直接建议直接使用 3.x 版。所以在这里建议您安装最新的Python 3.7 版。
想要安装 Python 3.7 可以 Python 官网([https://www.python.org/downloads/](https://www.python.org/downloads/))根据您机器的操作系统的类型下载对应的安装程序,然后运行安装即可。
![1](1.jpg)
## 喜闻乐见的HelloWorld
一般在学编程时都先学着写一个 “HelloWorld” 来表征一下自己的已经开始了编程之旅。那么我们来看一下怎样写 Python 版的 “HelloWorld” 。(本书使用的操作系统是 Windows )
首先在自己喜欢的一个目录中创建一个文本文件,并在文件中输入如下代码:
```python
print('Hello, World')
```
然后修改文件的名字,如 first.py。**(注意Python 代码文件的后缀名为 py )**
接着进入命令行,进入到 first.py 所在的目录。例如 first.py 在 D:/code 目录下,所以需要在命令行输入:
```shell
cd d:/code
```
最后只要在命令行输入如下命令就可以运行我们写好的程序了。
```shell
python first.py
```
运行程序后看到的输出和我们的预期一致。
```python
Hello, World
```

@ -0,0 +1,62 @@
# 1.1.2:数据类型与变量
## Python内置数据类型
如果让您解释一下什么是计算机的话,您可能会说计算机顾名思义就是可以做数学计算的机器。的确如此,因此,计算机程序理所当然地可以处理各种数值。但是,计算机能处理的远不止数值,还可以处理文本、图形、视频等各种各样的数据,不同的数据,需要定义不同的数据类型。在 Python 中,能够直接处理的数据类型称为内置数据类型,内置数据类型有:**整数、浮点数、字符串和布尔值**。
### 整数
Python 为什么这么流行呢?主要原因有两个:
- 首先是因为本身语法简单而且提供了非常完善的基础代码库覆盖了如网络、文件、GUI、数据库、正则表达式等大量内容。您可别小看了这些基础代码库它会让我们在实现功能时减少我们的代码量将我们从底层代码中解放出来更加的关心我们需要实现的业务功能。
- 其次是大家觉得 Python 这么好用,就会有很多具有开源精神的开发者去开发各种各样的第三方模块。接着大家可能会去尝试使用这些模块,然后发现这些模块挺好用的,然后就可能会把这些好用的模块或者 Python 语言推荐给自己的朋友、同事。就这样,不断地完善了 Python 的生态。以前用 C 语言想要实现一个功能可能需要 30 行代码,而用 Python 可能只需要 1 行代码。这也就使得编程的门槛越来越低,越来越流行。
事物都有两面性,既然 Python 有这么大的优点,那肯定也有不小的缺点。 Python 最为致命的确定就是运行速度慢。由于 Python 是解释型语言,您所编写的代码在执行时,解释器会一行一行的翻译成 CPU 能理解的机器码,这个翻译过程是非常耗时的,所以 Python 的运行速度很慢。而像 C 语言所编写的程序在运行前会直接将代码翻译成 CPU 能够理解的机器码,所以 C 语言编写的程序运行时非常快。
不过值得庆幸的是,大量的应用程序不需要这么快的运行速度,因为用户根本感觉不出来。例如开发一个下载 短视频 的网络应用程序C 程序的运行时间需要0.001 秒,而 Python 程序的运行时间需要 0.1 秒,慢了 100 倍,但由于网络更慢,需要等待 5 秒。您可以思考一下,用户真的能感觉到 5.001 秒和 5.1秒 的区别吗?
这就好比布加迪威龙和五菱宏光在北京三环路上行驶的道理一样,虽然理论时速高达 430 公里,但由于三环路堵车的时速只有 20 公里,因此,作为乘客,您感觉的时速是 20 公里。
所以选择 Python 作为编程语言是一种比较明智的选额。
## 如何安装Python
相信现在您可能已经迫不及待地想要在自己的机器上安装 Python 并开始 Python 之旅了。不过在安装 Python 前还需要了解一个知识,就是 Python 其实有两个不兼容的版本,一个是 2.x 版,另一个是 3.x 版。但由于 2.x 版只维护到 2020 年,而且 Python 官方都直接建议直接使用 3.x 版。所以在这里建议您安装最新的Python 3.7 版。
想要安装 Python 3.7 可以 Python 官网([https://www.python.org/downloads/](https://www.python.org/downloads/))根据您机器的操作系统的类型下载对应的安装程序,然后运行安装即可。
![1](1.jpg)
## 喜闻乐见的HelloWorld
一般在学编程时都先学着写一个 “HelloWorld” 来表征一下自己的已经开始了编程之旅。那么我们来看一下怎样写 Python 版的 “HelloWorld” 。(本书使用的操作系统是 Windows )
首先在自己喜欢的一个目录中创建一个文本文件,并在文件中输入如下代码:
```python
print('Hello, World')
```
然后修改文件的名字,如 first.py。**(注意Python 代码文件的后缀名为 py )**
接着进入命令行,进入到 first.py 所在的目录。例如 first.py 在 D:/code 目录下,所以需要在命令行输入:
```shell
cd d:/code
```
最后只要在命令行输入如下命令就可以运行我们写好的程序了。
```shell
python first.py
```
运行程序后看到的输出和我们的预期一致。
![2](2.jpg)

Binary file not shown.

After

Width:  |  Height:  |  Size: 20 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 3.9 KiB

@ -0,0 +1,2 @@
# 第一章Python基础知识

Binary file not shown.

After

Width:  |  Height:  |  Size: 14 KiB

@ -0,0 +1,148 @@
# 2.1.1ndarray对象
## 怎样安装 NumPy
NumPy (Numerical Python) 是 Python 语言的一个扩展程序库,支持大量的维度数组与矩阵运算,此外也针对数组运算提供大量的数学函数库。是在学习机器学习、深度学习之前应该掌握的一个非常基本且实用的 python 库。
想要安装 NumPy 其实非常简单,进入命令行,输入如下代码即可:
```shell
pip install numpy
```
## 什么是 ndarray 对象
NumPy 为什么能够受到各个数据科学从业人员的青睐与追捧,其实很大程度上是因为 NumPy 在向量计算方面做了很多优化,接口也非常友好。而这些其实都是在围绕着 NumPy 的一个核心数据结构 ndarray 。
ndarray 的全称是 N-Dimension Arrary ,字面意义上其实已经表明了一个 ndarray 对象就是一个 N 维数组。但要注意的是ndarray 是**同质**的。同质的意思就是说** N 维数组里的所有元素必须是属于同一种数据类型的**。**(PS: python 中的 list 是异质的)**
ndarray 对象实例化好了之后,包含了一些基本的属性。比如 shape ndim size dtype 。其中:
- shape : ndarray 对象的形状,由一个 tuple 表示
- ndim : ndarray 对象的维度
- size : ndarray 对象中元素的数量
- dtype : ndarray 对象中元素的数据类型,例如 int64 float32 等。
来看个例子,假设现在有一个 3 行 5 列的矩阵( ndarray )如下:
```python
array([[ 0, 1, 2, 3, 4],
[ 5, 6, 7, 8, 9],
[10, 11, 12, 13, 14]])
```
那么该 ndarray 的 shape 是 (3, 5) 。(代表 3 行 5 列)ndim 是 2 (因为矩阵有行和列两个维度)size 是 15 (因为矩阵总共有 15 个元素) dtype 是 int32 (因为矩阵中元素都是整数,并且用 32 位整型足够表示矩阵中的元素)
打印这些属性的示例代码如下:
```python
# 导入numpy并取别名为np
import numpy as np
# 构造ndarray
a = np.arange(15).reshape(3, 5)
# 打印a的shapendimsizedtype
print(a.shape)
print(a.ndim)
print(a.size)
print(a.dtype)
```
输出如下:
```python
(3, 5)
2
15
int32
```
## 如何实例化 ndarray 对象
实例化 ndarray 对象的函数有很多种,但最为常用的函数是 array zeros ones 以及 empty 。
### 使用 array 函数实例化 ndarray 对象
如果你手头上有一个 python 的 list ,想要将这个 list 转成 ndarray ,此时可以使用 NumPy 中的 array 函数将 list 中的值作为初始值,来实例化一个 ndarray 对象。代码如下:
```python
import numpy as np
# 使用列表作为初始值实例化ndarray对象a
a = np.array([2,3,4])
# 打印ndarray对象a
print(a)
```
输出如下:
```python
[2, 3, 4]
```
### 使用 zeros ones empty 函数实例化 ndarray 对象
通常在写代码的时候,数组中元素的值一般都喜欢先初始化成 0 ,如果使用 array 的方式实例化 ndarray 对象的话,虽然能实现功能,但显得很麻烦(**首先要有一个全是 0 的 list**)。那有没有简单粗暴的方式呢,有!!那就是 zeros 函数,你只需要把 ndarray 的 shape 作为参数传进去即可。代码如下:
```python
import numpy as np
# 实例化ndarray对象aa是一个3行4列的矩阵矩阵中元素全为0
a = np.zeros((3, 4))
# 打印ndarray对象a
print(a)
```
输出如下:
```python
[[0. 0. 0. 0.]
[0. 0. 0. 0.]
[0. 0. 0. 0.]]
```
如果想把数组中的元素全部初始化成 1 ,聪明的你应该能想到就是用 ones 函数oens 的用法与 zeros 一致。代码如下:
```python
import numpy as np
# 实例化ndarray对象aa是一个3行4列的矩阵矩阵中元素全为1
a = np.ones((3, 4))
# 打印ndarray对象a
print(a)
```
输出如下:
```python
[[1. 1. 1. 1.]
[1. 1. 1. 1.]
[1. 1. 1. 1.]]
```
如果 01大法 满足不了你,想要用随机值作为初始值来实例化 ndarray 对象empty 函数能够满足你。 empty 的使用方式与 zeros 和 ones 如出一辙,代码如下:
```python
import numpy as np
# 实例化ndarray对象aa是一个2行3列的矩阵矩阵中元素全为随机值
a = np.empty((2, 3))
# 打印ndarray对象a
print(a)
```
输出可能如下:
```python
[[2.67276450e+185 1.69506143e+190 1.75184137e+190]
[9.48819320e+077 1.63730399e-306 0.00000000e+000]]
```

@ -0,0 +1,90 @@
# 2.1.2:形状操作
## 改变形状
上一节介绍了怎样实例化 ndarray 对象,比如想实例化一个 3 行 4 列的二维数组,并且数组中的值全为 0 。就可能会写如下代码:
```python
import numpy as np
a = np.zeros((3, 4))
```
那如果想把 a 变成 4 行 3 列的二维数组,怎么办呢?机智的您可能会想到这样的代码:
```python
import numpy as np
a = np.zeros((3, 4))
# 直接修改shape属性
a.shape = [4, 3]
```
最后您会发现,这样的代码可以完成功能,但是这种直接改属性的方式太粗暴了,不符合良好的编程规范。
更加**优雅的解决方式**是使用 NumPy 为我们提供了一个用来改变 ndarray 对象的 shape 的函数,叫**reshape**。
NumPy 为了照顾偏向于面向对象或者这偏向于面向过程这两种不同风格的程序员,提供了两种调用**reshape**函数的方式(**其实很多函数都提供了两种风格的接口**)。
如果你更偏向于面向对象,那么你可以想象成 ndarray 对象中提供好了一个叫 reshape 成员函数。代码如下:
```python
import numpy as np
a = np.zeros((3, 4))
# 调用a的成员函数reshape将3行4列改成4行3列
a = a.reshape((4, 3))
```
如果你更偏向于面向过程NumPy 在它的作用域内实现了 reshape 函数。代码如下:
```python
import numpy as np
a = np.zeros((3, 4))
# 调用reshape函数将a变形成4行3列
a = np.reshape(a, (4, 3))
```
**不过需要注意的是,不管是哪种方式的 reshape ,都不会改变源 ndarray 的形状,而是将源 ndarray 进行深拷贝并进行变形操作,最后再将变形后的数组返回出去。也就是说如果代码是`np.reshape(a, (4, 3))`那么 a 的形状不会被修改!**
如果想优雅的直接改变源 ndarray 的形状,可以使用 resize 函数。代码如下:
```python
import numpy as np
a = np.zeros((3, 4))
# 将a从3行4列的二维数组变成一个有12个元素的一维数组
a.resize(12)
print(a)
```
输出如下:
```python
[0. 0. 0. 0. 0. 0. 0. 0. 0. 0. 0. 0.]
```
有的时候懒得去算每个维度上的长度是多少,比如现在有一个 6 行 8 列的 ndarray ,然后想把它变形成有 2 列的 ndarray (**行的数量我懒得去想**),此时我们可以在行的维度上传个 -1 即可,代码如下:
```python
import numpy as np
a = np.zeros((6, 8))
# 行的维度上填-1会让numpy自己去推算出行的数量很明显行的数量应该是24
a = a.reshape((-1, 2))
```
也就是说在变形操作时,如果某个维度上的值为 -1 ,那么该维度上的值会根据其他维度上的值自动推算。
**-1 虽好,可不能贪杯!如果代码改成 `a = a.reshape((-1, -1))` NumPy 会认为你是在刁难他,并向你抛出异常 `ValueError: can only specify one unknown dimension`。**

@ -0,0 +1,170 @@
# 2.1.3:基础操作
## 算术运算
如果想要对 ndarray 对象中的元素做 elementwise (**逐个元素地**)的算术运算非常简单,加减乘除即可。代码如下:
```python
import numpy as np
a = np.array([0, 1, 2, 3])
# a中的所有元素都加2结果为[2, 3, 4, 5]
b = a + 2
# a中的所有元素都减2结果为[-2, -1, 0, 1]
c = a - 2
# a中的所有元素都乘以2结果为[0, 2, 4, 6]
d = a * 2
# a中的所有元素都平方结果为[0, 1, 4, 9]
e = a ** 2
# a中的所有元素都除以2结果为[0, 0.5, 1, 1.5]
f = a / 2
# a中的所有元素都与2比结果为[True, True, False, False]
g = a < 2
```
## 矩阵运算
相同 shape 的矩阵 A 与矩阵 B 之间想要做 elementwise 运算也很简单,加减乘除即可。代码如下:
```python
import numpy as np
a = np.array([[0, 1], [2, 3]])
b = np.array([[1, 1], [3, 2]])
# a与b逐个元素相加结果为[[1, 2], [5, 5]]
c = a + b
# a与b逐个元素相减结果为[[-1, 0], [-1, 1]]
d = a - b
# a与b逐个元素相乘结果为[[0, 1], [6, 6]]
e = a * b
# a的逐个元素除以b的逐个元素结果为[[0., 1.], [0.66666667, 1.5]]
f = a / b
# a与b逐个元素做幂运算结果为[[0, 1], [8, 9]]
g = a ** b
# a与b逐个元素相比较结果为[[True, False], [True, False]]
h = a < b
```
细心的同学应该发现了, * 只能做 elementwise 运算,如果想做真正的矩阵乘法运算显然不能用 * 。 NumPy 提供了 @ 和 dot 函数来实现矩阵乘法。代码如下:
```python
import numpy as np
A = np.array([[1, 1], [0, 1]])
B = np.array([[2, 0], [3, 4]])
# @表示矩阵乘法矩阵A乘以矩阵B结果为[[5, 4], [3, 4]]
print(A @ B)
# 面向对象风格矩阵A乘以矩阵B结果为[[5, 4], [3, 4]]
print(A.dot(B))
# 面向过程风格矩阵A乘以矩阵B结果为[[5, 4], [3, 4]]
print(np.dot(A, B))
```
输出如下:
```python
[[5 4]
[3 4]]
[[5 4]
[3 4]]
[[5 4]
[3 4]]
```
## 简单统计
有的时候想要知道 ndarray 对象中元素的和是多少,最小值是多少,最小值在什么位置,最大值是多少,最大值在什么位置等信息。这个时候可能会想着写一个循环去遍历 ndarray 对象中的所有元素来进行统计。 NumPy 为了解放我们的双手,提供了 sum min max argmin argmax 等函数来实现简单的统计功能,代码如下:
```python
import numpy as np
a = np.array([[-1, 1, 2, 3], [4, 5, 6, 7], [8, 9, 10, 13]])
# 计算a中所有元素的和结果为67
print(a.sum())
# 找出a中最大的元素结果为13
print(a.max())
# 找出a中最小的元素结果为-1
print(a.min())
# 找出a中最大元素在a中的位置由于a中有12个元素位置从0开始计所以结果为11
print(a.argmax())
# 找出a中最小元素在a中位置结果为0
print(a.argmin())
```
输出如下:
```python
67
13
-1
11
0
```
有的时候,我们在统计时需要根据轴来统计。举个例子,公司员工的基本工资,绩效工资,年终奖的信息如下:
| 工号 | 基本工资 | 绩效工资 | 年终奖 |
| ------------ | ------------ | ------------ | ------------ |
| 1 | 3000 | 4000 | 20000 |
| 2 | 2700 | 5500 | 25000 |
| 3 | 2800 | 3000 | 15000 |
这样一个表格很明显,可以用 ndarray 来存储。代码如下:
```python
import numpy as np
info = np.array([[3000, 4000, 20000], [2700, 5500, 25000], [2800, 3000, 15000]])
```
info 实例化之后就有了维度和轴的概念,很明显 info 是个二维数组,所以它的**维度是 2 **。维度为 2 换句话来说就是 info 有**两个轴0 号轴与 1 号轴(轴的编号从 0 开始算)**。轴所指的方向如下图所示:
![轴示意图](1.jpg)
如果想要统计下这 3 位员工中基本工资、绩效工资与年终奖的最小值与最大值(**也就是说分别统计出每一列中的最小与最大值**)。我们可以沿着 0 号轴来统计。想要实现沿着哪个轴来统计,只需要修改 axis 即可,代码如下:
```python
import numpy as np
info = np.array([[3000, 4000, 20000], [2700, 5500, 25000], [2800, 3000, 15000]])
# 沿着0号轴统计结果为[2700, 3000, 15000]
print(info.min(axis=0))
# 沿着0号轴统计结果为[3000, 5500, 25000]
print(info.max(axis=0))
```
输出如下:
```python
[ 2700 3000 15000]
[ 3000 5500 25000]
```
**PS:当没有修改 axis 时axis 的值默认为 None 。意思是在统计时会把 ndarray 对象中所有的元素都考虑在内。**

@ -0,0 +1,149 @@
# 2.1.4:随机数生成
## 简单随机数生成
NumPy 的 random 模块下提供了许多生成随机数的函数,如果对于随机数的概率分布没有什么要求,则通常可以使用 random_sample 、choice 、randint 等函数来实现生成随机数的功能。
### random_sample
random_sample 用于生成区间为 [0, 1] 的随机数,需要填写的参数 size 表示生成的随机数的形状,比如 size=[2, 3] 那么则会生成一个 2 行 3 列的 ndarray ,并用随机值填充。示例代码如下:
```python
import numpy as np
print(np.random.random_sample(size=[2, 3]))
```
输出可能如下:
```python
[[0.32343809 0.38736262 0.42413616]
[0.86190206 0.27183736 0.12824812]]
```
### choice
如果想模拟像掷骰子、扔硬币等这种随机值是离散值,而且知道范围的可以使用 choice 实现。choice 的主要参数是 a 和 size 。 a 是个一维数组,代表你想从 a 中随机挑选size 是随机数生成后的形状。假如模拟 5 次掷骰子,代码如下:
```python
import numpy as np
'''
掷骰子时可能出现的点数为1, 2, 3, 4, 5, 6所以a=[1,2,3,4,5,6]
模拟5此掷骰子所以size=5
结果可能为 [6, 4, 3, 1, 3]
'''
print(np.random.choice(a=[1, 2, 3, 4, 5, 6], size=5))
```
输出可能如下:
```python
[6 4 3 1 3]
```
### randint
randint 的功能和 choice 差不多,只不过 randint 只能生成整数,而 choice 生成的数与 a 有关,如果 a 中有浮点数,那么 choice 会有概率挑选到浮点数。
randint 的参数有 3 个,分别为 low high 和 size 。其中 low 表示随机数生成时能够生成的最小值, high 表示随机数生成时能够生成的最大值减 1 。也就是说 randint 生成的随机数的区间为 [low, high) 。假如模拟 5 次掷骰子,代码如下:
```python
import numpy as np
'''
掷骰子时可能出现的点数为1, 2, 3, 4, 5, 6所以low=1,high=7
模拟5此掷骰子所以size=5
结果可能为 [6, 4, 3, 1, 3]
'''
print(np.random.randint(low=1, high=7, size=5)
```
输出可能如下:
```python
[6 4 3 1 3]
```
## 概率分布随机数生成
如果对于产生的随机数的概率分布有特别要求NumPy 同样提供了从指定的概率分布中采样得到的随机值的[接口](https://www.numpy.org/devdocs/reference/routines.random.html?highlight=random#module-numpy.random)。在这里主要介绍高斯分布。
高斯分布又称为正态分布,其分布图形如下:
![高斯分布](2.jpg)
上图中横轴为随机变量的值(**在这里可以看成是产生的随机值**),纵轴表示随机变量对应的概率(**在这里可以看成是随机值被挑选到的概率**)。
其实在日常生活中有很多现象或多或少都符合高斯分布。比如某个地方的高考分数,一般来说高考分数非常低和高考分数非常高的学生都比较少,而分数中规中矩的学生比较多,如果所统计的数据足够大,那么高考分数的概率分布也会和上图一样,**中间高,两边低**。
想要实现根据高斯分布来产生随机值,可以使用 normal 函数。示例代码如下:
```python
import numpy as np
'''
根据高斯分布生成5个随机数
结果可能为:[1.2315868, 0.45479902, 0.24923969, 0.42976352, -0.68786445]
从结果可以看出0.4左右得值出现的次数比较高1和-0.7左右的值出现的次数比较低。
'''
print(np.random.normal(size=5)
```
输出可能如下:
```python
[1.2315868 0.45479902 0.24923969 0.42976352 -0.68786445]
```
其中 normal 函数除了 size 参数外,还有两个比较重要的参数就是 loc 和 scale ,它们分别代表高斯分布的**均值**和**方差**。 loc 影响的分布中概率最高的点的位置,假设 loc=2 ,那么分布中概率最高的点的位置就是 2 。下图体现了 loc 对分布的影响其中蓝色f分布的 loc=0 ,红色分布的 loc=5 。
![均值对高斯分布的影响](3.jpg)
scale 影响的是分布图形的胖瘦scale 越小分布就越又高又瘦scale 越大,分布就越又矮又胖。下图体现了 scale 对分布的影响其中蓝色分布的scale=0.5 ,红色分布的 scale=1.0 。
![方差对高斯分布的影响](4.jpg)
所以,想要根据均值为 1 ,方差为 10 的高斯分布来生成 5 个随机值,代码如下:
```python
import numpy as np
print(np.random.normal(loc=1, scale=10, size=5)
```
输出可能如下:
```python
[1.52414964 7.08225325 13.26337651 4.29866004 9.89972241]
```
## 随机种子
前面说了这么多随机数生成的方法,那么随机数是怎样生成的呢?其实计算机产生的随机数是由随机种子根据一定的计算方法计算出来的数值。**所以只要计算方法固定,随机种子固定,那么产生的随机数就不会变!**
如果想要让每次生成的随机数不变,那么就需要设置随机种子(**随机种子其实就是一个0到4294967295的整数**)。设置随机种子很长简单,调用 seed 函数并设置随机种子即可,代码如下:
```python
import numpy as np
# 设置随机种子为233
np.random.seed(seed=233)
data = [1, 2, 3, 4]
# 随机从data中挑选数字结果为4
print(np.random.choice(data))
# 随机从data中挑选数字结果为4
print(np.random.choice(data))
```
输出如下:
```python
4
4
```

@ -0,0 +1,158 @@
# 2.1.5:索引与切片
## 索引
ndarray 的索引其实和 python 的 list 的索引极为相似。元素的索引从 0 开始。代码如下:
```python
import numpy as np
# a中有4个元素那么这些元素的索引分别为0123
a = np.array([2, 15, 3, 7])
# 打印第2个元素
# 索引1表示的是a中的第2个元素
# 结果为15
print(a[1])
# b是个2行3列的二维数组
b = np.array([[1, 2, 3], [4, 5, 6]])
# 打印b中的第1行
# 总共就2行所以行的索引分别为01
# 结果为[1, 2, 3]
print(b[0])
# 打印b中的第2行第2列的元素
# 结果为5
print(b[1][1])
```
输出如下:
```python
15
[1 2 3]
5
```
## 遍历
ndarray 的遍历方式与 python 的 list 的遍历方式也极为相似,示例代码如下:
```python
import numpy as np
a = np.array([2, 15, 3, 7])
# 使用for循环将a中的元素取出来后打印
for element in a:
print(element)
# 根据索引遍历a中的元素并打印
for idx in range(len(a)):
print(a[idx])
# b是个2行3列的二维数组
b = np.array([[1, 2, 3], [4, 5, 6]])
# 将b展成一维数组后遍历并打印
for element in b.flat:
print(element)
# 根据索引遍历b中的元素并打印
for i in range(len(b)):
for j in range(len(b[0])):
print(b[i][j])
```
输出如下:
```python
2
15
3
7
2
15
3
7
1
2
3
4
5
6
1
2
3
4
5
6
```
## 切片
ndarray 的切片方式与 python 的 list 的遍历方式也极为相似,对切片不熟的同学也不用慌,套路很简单,就是用索引。
假设想要将下图中紫色部分切片出来,就需要确定行的范围和列的范围。由于紫色部分行的范围是 0 到 2 ,所以切片时行的索引范围是 0:3 (**索引范围是左闭右开**);又由于紫色部分列的范围也是 0 到 2 ,所以切片时列的索引范围也是 0:3 (**索引范围是左闭右开**)。最后把行和列的索引范围整合起来就是 [0:3, 0:3] (**逗号左边是行的索引范围**)。当然有时为了方便0 可以省略,也就是 [:3, :3] 。
![切片示意图](5.jpg)
切片示例代码如下:
```python
import numpy as np
# a中有4个元素那么这些元素的索引分别为0123
a = np.array([2, 15, 3, 7])
'''
将索引从1开始到最后的所有元素切片出来并打印
结果为[15 3 7]
'''
print(a[1:])
'''
将从倒数第2个开始到最后的所有元素切片出来并打印
结果为[3 7]
'''
print(a[-2:])
'''
将所有元素倒序切片并打印
结果为[ 7 3 15 2]
'''
print(a[::-1])
# b是个2行3列的二维数组
b = np.array([[1, 2, 3], [4, 5, 6]])
'''
将第2行的第2列到第3列的所有元素切片并打印
结果为[[5 6]]
'''
print(b[1:, 1:3])
'''
将第2列到第3列的所有元素切片并打印
结果为[[2 3]
[5 6]]
'''
print(b[:, 1:3])
```
输出如下:
```python
[15 3 7]
[3 7]
[7 3 15 2]
[[5 6]]
[[2 3]
[5 6]]
```

Binary file not shown.

After

Width:  |  Height:  |  Size: 11 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 11 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 9.6 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 12 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 20 KiB

@ -0,0 +1,170 @@
# 2.1.3:基础操作
## 算术运算
如果想要对 ndarray 对象中的元素做 elementwise (**逐个元素地**)的算术运算非常简单,加减乘除即可。代码如下:
```python
import numpy as np
a = np.array([0, 1, 2, 3])
# a中的所有元素都加2结果为[2, 3, 4, 5]
b = a + 2
# a中的所有元素都减2结果为[-2, -1, 0, 1]
c = a - 2
# a中的所有元素都乘以2结果为[0, 2, 4, 6]
d = a * 2
# a中的所有元素都平方结果为[0, 1, 4, 9]
e = a ** 2
# a中的所有元素都除以2结果为[0, 0.5, 1, 1.5]
f = a / 2
# a中的所有元素都与2比结果为[True, True, False, False]
g = a < 2
```
## 矩阵运算
相同 shape 的矩阵 A 与矩阵 B 之间想要做 elementwise 运算也很简单,加减乘除即可。代码如下:
```python
import numpy as np
a = np.array([[0, 1], [2, 3]])
b = np.array([[1, 1], [3, 2]])
# a与b逐个元素相加结果为[[1, 2], [5, 5]]
c = a + b
# a与b逐个元素相减结果为[[-1, 0], [-1, 1]]
d = a - b
# a与b逐个元素相乘结果为[[0, 1], [6, 6]]
e = a * b
# a的逐个元素除以b的逐个元素结果为[[0., 1.], [0.66666667, 1.5]]
f = a / b
# a与b逐个元素做幂运算结果为[[0, 1], [8, 9]]
g = a ** b
# a与b逐个元素相比较结果为[[True, False], [True, False]]
h = a < b
```
细心的同学应该发现了, * 只能做 elementwise 运算,如果想做真正的矩阵乘法运算显然不能用 * 。 NumPy 提供了 @ 和 dot 函数来实现矩阵乘法。代码如下:
```python
import numpy as np
A = np.array([[1, 1], [0, 1]])
B = np.array([[2, 0], [3, 4]])
# @表示矩阵乘法矩阵A乘以矩阵B结果为[[5, 4], [3, 4]]
print(A @ B)
# 面向对象风格矩阵A乘以矩阵B结果为[[5, 4], [3, 4]]
print(A.dot(B))
# 面向过程风格矩阵A乘以矩阵B结果为[[5, 4], [3, 4]]
print(np.dot(A, B))
```
输出如下:
```python
[[5 4]
[3 4]]
[[5 4]
[3 4]]
[[5 4]
[3 4]]
```
## 简单统计
有的时候想要知道 ndarray 对象中元素的和是多少,最小值是多少,最小值在什么位置,最大值是多少,最大值在什么位置等信息。这个时候可能会想着写一个循环去遍历 ndarray 对象中的所有元素来进行统计。 NumPy 为了解放我们的双手,提供了 sum min max argmin argmax 等函数来实现简单的统计功能,代码如下:
```python
import numpy as np
a = np.array([[-1, 1, 2, 3], [4, 5, 6, 7], [8, 9, 10, 13]])
# 计算a中所有元素的和结果为67
print(a.sum())
# 找出a中最大的元素结果为13
print(a.max())
# 找出a中最小的元素结果为-1
print(a.min())
# 找出a中最大元素在a中的位置由于a中有12个元素位置从0开始计所以结果为11
print(a.argmax())
# 找出a中最小元素在a中位置结果为0
print(a.argmin())
```
输出如下:
```python
67
13
-1
11
0
```
有的时候,我们在统计时需要根据轴来统计。举个例子,公司员工的基本工资,绩效工资,年终奖的信息如下:
| 工号 | 基本工资 | 绩效工资 | 年终奖 |
| ------------ | ------------ | ------------ | ------------ |
| 1 | 3000 | 4000 | 20000 |
| 2 | 2700 | 5500 | 25000 |
| 3 | 2800 | 3000 | 15000 |
这样一个表格很明显,可以用 ndarray 来存储。代码如下:
```python
import numpy as np
info = np.array([[3000, 4000, 20000], [2700, 5500, 25000], [2800, 3000, 15000]])
```
info 实例化之后就有了维度和轴的概念,很明显 info 是个二维数组,所以它的**维度是 2 **。维度为 2 换句话来说就是 info 有**两个轴0 号轴与 1 号轴(轴的编号从 0 开始算)**。轴所指的方向如下图所示:
![轴示意图](1.jpg)
如果想要统计下这 3 位员工中基本工资、绩效工资与年终奖的最小值与最大值(**也就是说分别统计出每一列中的最小与最大值**)。我们可以沿着 0 号轴来统计。想要实现沿着哪个轴来统计,只需要修改 axis 即可,代码如下:
```python
import numpy as np
info = np.array([[3000, 4000, 20000], [2700, 5500, 25000], [2800, 3000, 15000]])
# 沿着0号轴统计结果为[2700, 3000, 15000]
print(info.min(axis=0))
# 沿着0号轴统计结果为[3000, 5500, 25000]
print(info.max(axis=0))
```
输出如下:
```python
[ 2700 3000 15000]
[ 3000 5500 25000]
```
**PS:当没有修改 axis 时axis 的值默认为 None 。意思是在统计时会把 ndarray 对象中所有的元素都考虑在内。**

@ -0,0 +1,149 @@
# 2.1.4:随机数生成
## 简单随机数生成
NumPy 的 random 模块下提供了许多生成随机数的函数,如果对于随机数的概率分布没有什么要求,则通常可以使用 random_sample 、choice 、randint 等函数来实现生成随机数的功能。
### random_sample
random_sample 用于生成区间为 [0, 1] 的随机数,需要填写的参数 size 表示生成的随机数的形状,比如 size=[2, 3] 那么则会生成一个 2 行 3 列的 ndarray ,并用随机值填充。示例代码如下:
```python
import numpy as np
print(np.random.random_sample(size=[2, 3]))
```
输出可能如下:
```python
[[0.32343809 0.38736262 0.42413616]
[0.86190206 0.27183736 0.12824812]]
```
### choice
如果想模拟像掷骰子、扔硬币等这种随机值是离散值,而且知道范围的可以使用 choice 实现。choice 的主要参数是 a 和 size 。 a 是个一维数组,代表你想从 a 中随机挑选size 是随机数生成后的形状。假如模拟 5 次掷骰子,代码如下:
```python
import numpy as np
'''
掷骰子时可能出现的点数为1, 2, 3, 4, 5, 6所以a=[1,2,3,4,5,6]
模拟5此掷骰子所以size=5
结果可能为 [6, 4, 3, 1, 3]
'''
print(np.random.choice(a=[1, 2, 3, 4, 5, 6], size=5))
```
输出可能如下:
```python
[6 4 3 1 3]
```
### randint
randint 的功能和 choice 差不多,只不过 randint 只能生成整数,而 choice 生成的数与 a 有关,如果 a 中有浮点数,那么 choice 会有概率挑选到浮点数。
randint 的参数有 3 个,分别为 low high 和 size 。其中 low 表示随机数生成时能够生成的最小值, high 表示随机数生成时能够生成的最大值减 1 。也就是说 randint 生成的随机数的区间为 [low, high) 。假如模拟 5 次掷骰子,代码如下:
```python
import numpy as np
'''
掷骰子时可能出现的点数为1, 2, 3, 4, 5, 6所以low=1,high=7
模拟5此掷骰子所以size=5
结果可能为 [6, 4, 3, 1, 3]
'''
print(np.random.randint(low=1, high=7, size=5)
```
输出可能如下:
```python
[6 4 3 1 3]
```
## 概率分布随机数生成
如果对于产生的随机数的概率分布有特别要求NumPy 同样提供了从指定的概率分布中采样得到的随机值的[接口](https://www.numpy.org/devdocs/reference/routines.random.html?highlight=random#module-numpy.random)。在这里主要介绍高斯分布。
高斯分布又称为正态分布,其分布图形如下:
![高斯分布](2.jpg)
上图中横轴为随机变量的值(**在这里可以看成是产生的随机值**),纵轴表示随机变量对应的概率(**在这里可以看成是随机值被挑选到的概率**)。
其实在日常生活中有很多现象或多或少都符合高斯分布。比如某个地方的高考分数,一般来说高考分数非常低和高考分数非常高的学生都比较少,而分数中规中矩的学生比较多,如果所统计的数据足够大,那么高考分数的概率分布也会和上图一样,**中间高,两边低**。
想要实现根据高斯分布来产生随机值,可以使用 normal 函数。示例代码如下:
```python
import numpy as np
'''
根据高斯分布生成5个随机数
结果可能为:[1.2315868, 0.45479902, 0.24923969, 0.42976352, -0.68786445]
从结果可以看出0.4左右得值出现的次数比较高1和-0.7左右的值出现的次数比较低。
'''
print(np.random.normal(size=5)
```
输出可能如下:
```python
[1.2315868 0.45479902 0.24923969 0.42976352 -0.68786445]
```
其中 normal 函数除了 size 参数外,还有两个比较重要的参数就是 loc 和 scale ,它们分别代表高斯分布的**均值**和**方差**。 loc 影响的分布中概率最高的点的位置,假设 loc=2 ,那么分布中概率最高的点的位置就是 2 。下图体现了 loc 对分布的影响其中蓝色f分布的 loc=0 ,红色分布的 loc=5 。
![均值对高斯分布的影响](3.jpg)
scale 影响的是分布图形的胖瘦scale 越小分布就越又高又瘦scale 越大,分布就越又矮又胖。下图体现了 scale 对分布的影响其中蓝色分布的scale=0.5 ,红色分布的 scale=1.0 。
![方差对高斯分布的影响](4.jpg)
所以,想要根据均值为 1 ,方差为 10 的高斯分布来生成 5 个随机值,代码如下:
```python
import numpy as np
print(np.random.normal(loc=1, scale=10, size=5)
```
输出可能如下:
```python
[1.52414964 7.08225325 13.26337651 4.29866004 9.89972241]
```
## 随机种子
前面说了这么多随机数生成的方法,那么随机数是怎样生成的呢?其实计算机产生的随机数是由随机种子根据一定的计算方法计算出来的数值。**所以只要计算方法固定,随机种子固定,那么产生的随机数就不会变!**
如果想要让每次生成的随机数不变,那么就需要设置随机种子(**随机种子其实就是一个0到4294967295的整数**)。设置随机种子很长简单,调用 seed 函数并设置随机种子即可,代码如下:
```python
import numpy as np
# 设置随机种子为233
np.random.seed(seed=233)
data = [1, 2, 3, 4]
# 随机从data中挑选数字结果为4
print(np.random.choice(data))
# 随机从data中挑选数字结果为4
print(np.random.choice(data))
```
输出如下:
```python
4
4
```

@ -0,0 +1,158 @@
# 2.1.5:索引与切片
## 索引
ndarray 的索引其实和 python 的 list 的索引极为相似。元素的索引从 0 开始。代码如下:
```python
import numpy as np
# a中有4个元素那么这些元素的索引分别为0123
a = np.array([2, 15, 3, 7])
# 打印第2个元素
# 索引1表示的是a中的第2个元素
# 结果为15
print(a[1])
# b是个2行3列的二维数组
b = np.array([[1, 2, 3], [4, 5, 6]])
# 打印b中的第1行
# 总共就2行所以行的索引分别为01
# 结果为[1, 2, 3]
print(b[0])
# 打印b中的第2行第2列的元素
# 结果为5
print(b[1][1])
```
输出如下:
```python
15
[1 2 3]
5
```
## 遍历
ndarray 的遍历方式与 python 的 list 的遍历方式也极为相似,示例代码如下:
```python
import numpy as np
a = np.array([2, 15, 3, 7])
# 使用for循环将a中的元素取出来后打印
for element in a:
print(element)
# 根据索引遍历a中的元素并打印
for idx in range(len(a)):
print(a[idx])
# b是个2行3列的二维数组
b = np.array([[1, 2, 3], [4, 5, 6]])
# 将b展成一维数组后遍历并打印
for element in b.flat:
print(element)
# 根据索引遍历b中的元素并打印
for i in range(len(b)):
for j in range(len(b[0])):
print(b[i][j])
```
输出如下:
```python
2
15
3
7
2
15
3
7
1
2
3
4
5
6
1
2
3
4
5
6
```
## 切片
ndarray 的切片方式与 python 的 list 的遍历方式也极为相似,对切片不熟的同学也不用慌,套路很简单,就是用索引。
假设想要将下图中紫色部分切片出来,就需要确定行的范围和列的范围。由于紫色部分行的范围是 0 到 2 ,所以切片时行的索引范围是 0:3 (**索引范围是左闭右开**);又由于紫色部分列的范围也是 0 到 2 ,所以切片时列的索引范围也是 0:3 (**索引范围是左闭右开**)。最后把行和列的索引范围整合起来就是 [0:3, 0:3] (**逗号左边是行的索引范围**)。当然有时为了方便0 可以省略,也就是 [:3, :3] 。
![切片示意图](5.jpg)
切片示例代码如下:
```python
import numpy as np
# a中有4个元素那么这些元素的索引分别为0123
a = np.array([2, 15, 3, 7])
'''
将索引从1开始到最后的所有元素切片出来并打印
结果为[15 3 7]
'''
print(a[1:])
'''
将从倒数第2个开始到最后的所有元素切片出来并打印
结果为[3 7]
'''
print(a[-2:])
'''
将所有元素倒序切片并打印
结果为[ 7 3 15 2]
'''
print(a[::-1])
# b是个2行3列的二维数组
b = np.array([[1, 2, 3], [4, 5, 6]])
'''
将第2行的第2列到第3列的所有元素切片并打印
结果为[[5 6]]
'''
print(b[1:, 1:3])
'''
将第2列到第3列的所有元素切片并打印
结果为[[2 3]
[5 6]]
'''
print(b[:, 1:3])
```
输出如下:
```python
[15 3 7]
[3 7]
[7 3 15 2]
[[5 6]]
[[2 3]
[5 6]]
```

@ -0,0 +1,150 @@
# 2.2.1:堆叠操作
## stack
stack 的意思是堆叠的意思,所谓的堆叠就是将两个 ndarray 对象堆叠在一起组合成一个新的 ndarray 对象。根据堆叠的方向不同分为 hstack 以及 vstack 两种。
### hstack
假如你是某公司的 HR ,需要记录公司员工的一些基本信息。可能你现在已经记录了如下信息:
| 工号 | 姓名 | 出生年月 | 联系电话 |
| ------------ | ------------ | ------------ | ------------ |
| 1 | 张三 | 1988.12 | 13323332333 |
| 2 | 李四 | 1987.2 | 15966666666 |
| 3 | 王五 | 1990.1 | 13777777777 |
| 4 | 周六 | 1996.4 | 13069699696 |
世界上没有不变的需求,你的老板让你现在记录一下公司所有员工的居住地址和户籍地址。此时你只好屁颠屁颠的记录这些附加信息。然后可能会有这样的结果:
| 居住地址 | 户籍地址 |
| ------------ | ------------ |
| 江苏省南京市禄口机场宿舍202 | 江西省南昌市红谷滩新区天月家园A座2201 |
| 江苏省南京市禄口机场宿舍203 | 湖南省株洲市天元区新天华府11栋303 |
| 江苏省南京市禄口机场宿舍204 | 四川省成都市武侯祠安置小区1栋701 |
| 江苏省南京市禄口机场宿舍205 | 浙江省杭州市西湖区兴天世家B座1204 |
接下来你需要把之前记录的信息和刚刚记录好的附加信息整合起来,变成这样:
| 工号 | 姓名 | 出生年月 | 联系电话 | 居住地址 | 户籍地址 |
| ------------ | ------------ | ------------ | ------------ | ------------ | ------------ |
| 1 | 张三 | 1988.12 | 13323332333 | 江苏省南京市禄口机场宿舍202 | 江西省南昌市红谷滩新区天月家园A座2201 |
| 2 | 李四 | 1987.2 | 15966666666 | 江苏省南京市禄口机场宿舍203 | 湖南省株洲市天元区新天华府11栋303 |
| 3 | 王五 | 1990.1 | 13777777777 | 江苏省南京市禄口机场宿舍204 | 四川省成都市武侯祠安置小区1栋701 |
| 4 | 周六 | 1996.4 | 13069699696 | 江苏省南京市禄口机场宿舍205 | 浙江省杭州市西湖区兴天世家B座1204 |
看得出来,你在整合的时候是将两个表格(二维数组)在水平方向上堆叠在一起组合起来,拼接成一个新的表格(二维数组)。像这种行为称之为 hstack (horizontal stack)。
NumPy 提供了实现 hstack 功能的函数叫 hstack hstack 的使用套路代码如下:
```python
import numpy as np
a = np.array([[8, 8], [0, 0]])
b = np.array([[1, 8], [0, 4]])
'''
将a和b按元组中的顺序横向拼接
结果为:[[8, 8, 1, 8],
[0, 0, 0, 4]]
'''
print(np.hstack((a,b)))
c = np.array([[1, 2], [3, 4]])
'''
将a,b,c按元组中的顺序横向拼接
结果为:[[8, 8, 1, 8, 1, 2],
[0, 0, 0, 4, 3, 4]]
'''
print(np.hstack((a,b,c)))
```
输出如下:
```python
[[8 8 1 8]
[0 0 0 4]]
[[8 8 1 8 1 2]
[0 0 0 4 3 4]]
```
### vstack
你还是某公司的 HR ,你记录了公司员工的一些信息,如下:
| 工号 | 姓名 | 出生年月 | 联系电话 |
| ------------ | ------------ | ------------ | ------------ |
| 1 | 张三 | 1988.12 | 13323332333 |
| 2 | 李四 | 1987.2 | 15966666666 |
| 3 | 王五 | 1990.1 | 13777777777 |
| 4 | 周六 | 1996.4 | 13069699696 |
今天有两位新同事入职,你需要记录他们的信息,如下:
| 工号 | 姓名 | 出生年月 | 联系电话 |
| ------------ | ------------ | ------------ | ------------ |
| 5 | 刘七 | 1986.5 | 13323332331 |
| 6 | 胡八 | 1997.3 | 15966696669 |
然后你需要将新入职同事的信息和已经入职的员工信息整合在一起。
| 工号 | 姓名 | 出生年月 | 联系电话 |
| ------------ | ------------ | ------------ | ------------ |
| 1 | 张三 | 1988.12 | 13323332333 |
| 2 | 李四 | 1987.2 | 15966666666 |
| 3 | 王五 | 1990.1 | 13777777777 |
| 4 | 周六 | 1996.4 | 13069699696 |
| 5 | 刘七 | 1986.5 | 13323332331 |
| 6 | 胡八 | 1997.3 | 15966696669 |
在这种情况下,你在整合的时候是将两个表格(二维数组)在竖直方向上堆叠在一起组合起来,拼接成一个新的表格(二维数组)。像这种行为称之为 vstack (vertical stack)。
NumPy 提供了实现 vstack 功能的函数叫 vstack vstack 的示例代码如下:
```python
import numpy as np
a = np.array([[8, 8], [0, 0]])
b = np.array([[1, 8], [0, 4]])
'''
将a和b按元组中的顺序纵向拼接
结果为:[[8, 8]
[0, 0]
[1, 8]
[0, 4]]
'''
print(np.vstack((a,b)))
c = np.array([[1, 2], [3, 4]])
'''
将a,b,c按元组中的顺序纵向拼接
结果为:[[8 8]
[0 0]
[1 8]
[0 4]
[1 2]
[3 4]]
'''
print(np.vstack((a,b,c)))
```
输出如下:
```python
[[8 8]
[0 0]
[1 8]
[0 4]]
[[8 8]
[0 0]
[1 8]
[0 4]
[1 2]
[3 4]]
```

@ -0,0 +1,101 @@
# 2.2.2:花式索引与布尔索引
## 花式索引
花式索引(Fancy Indexing)是 NumPy 用来描述使用整型数组(**这里的数组,可以是 NumPy 的 ndarray ,也可以是 python 的 list**)作为索引。
Fancy Indexing 的意义是根据索引数组的值作为被索引数组( ndarray )的某个轴的下标来取值。对于使用一维整型数组作为索引来说,如果被索引数组( ndarray )是一维数组,那么索引的结果就是对应位置的元素;如果被索引数组( ndarray )是二维数组,那么就是对应下标的行。如下图所示:
![花式索引示意图](1.jpg)
示例代码如下:
```python
import numpy as np
arr = np.array(['zero','one','two','three','four'])
'''
打印arr中索引为1和4的元素
结果为:['one', 'four']
'''
print(arr[[1,4]])
arr = np.array([[1, 2, 3], [4, 5, 6], [7, 8, 9]])
'''
打印arr中索引为1和0的行
结果为:[[4, 5, 6],
[1, 2, 3]]
'''
print(arr[[1, 0]])
'''
打印arr中第2行第1列与第3行第2列的元素
结果为:[4, 8]
'''
print(arr[[1, 2], [0, 1]])
```
输出如下:
```python
['one' 'four']
[[4 5 6]
[1 2 3]]
[4 8]
```
## 布尔索引
我们可以通过一个布尔数组来索引目标数组,以此找出与布尔数组中值为 True 的对应的目标数组中的数据,从而达到筛选出想要的数据的功能。如下图所示:(**PS需要注意的是布尔数组的长度必须与被索引数组对应的轴的长度一致**)
![布尔索引示意图](2.jpg)
不过单纯的传入布尔数组进去有点蠢,有没有更加优雅的方式来使用布尔索引来达到筛选数据的效果呢?当然有!我们可以想办法根据我们的需求,构造出布尔数组,然后再通过布尔索引实现筛选数据的功能。
假设有公司员工绩效指数的数据如下(用一个一维的 ndarray 表示),现在想要把绩效指数大于 3.5 的筛选出来进行股权激励。
![公司员工绩效指数数据](3.jpg)
那首先就要构造出布尔数组,构造布尔数组很简单,`performance > 3.5`即可。此时会生成想要的布尔数组。
![布尔索引结果](4.jpg)
有了布尔数组就可以使用布尔索引来实现筛选数据的功能了。
![筛选过程示意图](5.jpg)
示例代码如下:
```python
import numpy as np
performance = np.array([3.25, 3.5, 3.75, 3.5, 3.25, 3.75])
'''
筛选出绩效高于3.5的数据
结果为:[3.75, 3.75]
'''
print(performance[performance > 3.5])
'''
筛选出绩效高于3.25并且低于4的数据
注意:&表示并且的意思可以看成是and。&左右两边必须加上()
结果为:[3.5 3.75 3.5 3.75]
'''
print(performance[(performance > 3.25) & (performance < 4)])
```
输出如下:
```python
[3.75 3.75]
[3.5 3.75 3.5 3.75]
```

Binary file not shown.

After

Width:  |  Height:  |  Size: 9.4 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 3.2 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 3.1 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 8.0 KiB

@ -0,0 +1,3 @@
# 第一部分: Python从0到1
Python凭借着其简单的语法、丰富的第三方模块使其成为了各种领域中最受欢迎的语言之一。在这一部分中将会从Python的安装开始一步一步地引导读者学会Python的语法知识以及在学习机器学习之前需要掌握的一些数据科学相关的第三方模块。准备好了吗Lets Go

@ -0,0 +1,2 @@
# Introduction

@ -0,0 +1,20 @@
# Summary
* [第一部分: Python从0到1](Part1/简介.md)
* [第一章: Python基础知识](Part1/Chapter1/简介.md)
* 1.1: Python基础
* [1.1.1 Hello, Python](Part1/Chapter1/1.1 Python基础/1.1.1 HelloPython.md)
* [1.1.2 数据类型与变量](Part1/Chapter1/1.1 Python基础/1.1.2 数据类型与运算.md)
* [1.1.3 运算符](README.md)
* [1.1.4 数据结构](README.md)
* [1.1.5 分支与循环](README.md)
* [1.2 Python进阶](README.md)
* [1.2.1 函数](README.md)
* 第二章:数值计算利器---NumPy
* 2.1: NumPy基础
* [2.1.1 ndarray对象](Part1/Chapter2/2.1 NumPy基础/2.1.1 ndarray对象.md)
* [2.1.2 形状操作](Part1/Chapter2/2.1 NumPy基础/2.1.2 形状操作.md)
* [2.1.3 基础操作](Part1/Chapter2/2.1 NumPy基础/2.1.3 基础操作.md)
* [2.1.4 随机数生成](Part1/Chapter2/2.1 NumPy基础/2.1.4 随机数生成.md)
* 2.1.5 索引与切片

File diff suppressed because it is too large Load Diff
Loading…
Cancel
Save