01. NumPy
1.1 NumPy库的概述与安装
1.1.1 NumPy概述
- NumPy几乎是一个无法回避的科学计算工具包,最常用的是它的N维数组对象,还有一些成熟的函数库,用于整合C/C++和Fortran代码的工具包、线性代数、傅里叶变换和随机数生成函数等。
NumPy提供了两种基本的对象:
高效矩阵与数组处理。
- 丰富的数值计算函数。
-
1.1.3 安装NumPy
安装命令:
pip install numpy
这里可能安装失败,Python安装第三方库失败基本上都是网络问题,可以换源解决。
- 国内常见的源:
- 换源安装命令:
pip install 第三方模块名 -i 镜像源
- 示例:用清华源安装numpy:
pip install numpy -i [https://pypi.tuna.tsinghua.edu.cn/simple/](https://pypi.tuna.tsinghua.edu.cn/simple/)
安装完成后,在编码时需要先导入NumPy库:
import numpy as np
1.2 NumPy中数组的创建
1.2.1 zeros((x, y), dtype=type)
np.zero((x, y))函数可以用于生成一个x行y列的数组,且数组中所有元素为0。 ```python import numpy as np
arr = np.zeros((4, 5)) print(arr)
“”” 运行结果: [[0. 0. 0. 0. 0.] [0. 0. 0. 0. 0.] [0. 0. 0. 0. 0.] [0. 0. 0. 0. 0.]] “””
<a name="vW8Ll"></a>
#### 1.2.2 ones((x, y), dtype=type)
- 与zeros基本一致,唯一的差别就在于数组中所有元素为1。
```python
import numpy as np
arr = np.ones((4, 5))
print(arr)
"""
运行结果:
[[1. 1. 1. 1. 1.]
[1. 1. 1. 1. 1.]
[1. 1. 1. 1. 1.]
[1. 1. 1. 1. 1.]]
"""
- 若将dtype指定为bool,则将得到一个全True的数组。(zeros也有这样的操作,得到全False的数组) ```python import numpy as np
arr = np.ones((4, 5), dtype=bool) print(arr)
“”” 运行结果: [[ True True True True True] [ True True True True True] [ True True True True True] [ True True True True True]] “””
<a name="ZTVAD"></a>
#### 1.2.3 array(lst, dtype=type)
- 可以用np.array(lst)函数将一个列表转换成一个数组。
```python
import numpy as np
lst = [1, 2, 3, 4]
arr = np.array(lst)
print(arr) # [1 2 3 4]
- 同时,还可以指定dtype,为数组中的元素明确类型。 ```python import numpy as np
lst = [1, 2, 3, 4] arr = np.array(lst, dtype=float) print(arr) # [1. 2. 3. 4.]
- 此外,还可以使用array()函数定义二维数组:
```python
import numpy as np
arr = np.array([
[1, 'A'],
[2, 'B'],
[3, 'C'],
[4, 'D']
])
print(arr)
"""
运行结果:
[['1' 'A']
['2' 'B']
['3' 'C']
['4' 'D']]
"""
1.2.4 arange(start, end, step)
- np.arange(start, end, step)函数用于生成从start开始到end结束的一段步长为step的数组。(步长缺省为1) ```python import numpy as np
arr = np.arange(1, 10, 3) print(arr) # [1 4 7]
<a name="ccZMu"></a>
#### 1.2.5 zeros_like(arr)
- zeros_like(arr)函数会生成一个形状与arr相同的数组,但数组中的所有元素都为0。
```python
import numpy as np
arr = np.array([
[1, 2, 3],
[4, 5, 6],
[7, 8, 9]
])
zero_arr = np.zeros_like(arr)
print(zero_arr)
"""
运行结果:
[[0 0 0]
[0 0 0]
[0 0 0]]
"""
1.2.6 linspace(start, end, n)
- linspace(start, end, n)会生成一个从start到end的等差数列,中间的数据有n个。
- 注意:与Python中其他数据类型都不同,linspace(start, end, n)生成的数据不是[start, end)的,而是[start, end]的。 ```python import numpy as np
arr = np.linspace(5, 25, 3) print(arr) # [ 5. 15. 25.]
<a name="g3e7o"></a>
#### 1.2.7 random.normal(loc=0.0, scale=1.0, size=None)
- random.normal(loc=0.0, scale=1.0, size=None)函数会从正态分布中抽取随机样本生成一个数组。
- loc:分布的平均值。
- scala:标注差。
- size:数组的形状。
```python
import numpy as np
arr = np.random.normal(size=(2,2)) # 生成一个2*2的随机数组。
print(arr)
"""
运行结果:
[[-0.25212173 -0.71369917]
[-0.76119745 0.37228655]]
"""
1.3 数组的规模
1.3.1 array.ndim
- array.ndim可以获取一个数组的维度。 ```python import numpy as np
arr = np.array([ [1, 2, 3], [4, 5, 6], [7, 8, 9] ]) print(arr.ndim) # 2
<a name="fqEFh"></a>
#### 1.3.2 array.shape
- array.shape可以获取一个数组的形状。
```python
import numpy as np
arr = np.array([
[1, 'A'],
[2, 'B'],
[3, 'C'],
[4, 'D']
])
print(arr.shape) # (4, 2)
结果(4, 2)的解读:
array.size可以获取一个数组的大小,size实际上就是sharp得到的(x, y)中x * y的结果。 ```python import numpy as np
arr = np.array([ [1, ‘A’], [2, ‘B’], [3, ‘C’], [4, ‘D’] ]) print(arr.size) # 8
<a name="zz5gb"></a>
#### 1.3.4 array.reshape(x, y)
- array.reshape(x, y)函数用于将数组的维度重置为x行y列。
```python
import numpy as np
arr1 = np.arange(100)
print(arr1) # [ 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 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99]
print(arr1.shape) # (100,)
arr2 = arr1.reshape(10, 10)
print(arr2)
"""
[[ 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]
[30 31 32 33 34 35 36 37 38 39]
[40 41 42 43 44 45 46 47 48 49]
[50 51 52 53 54 55 56 57 58 59]
[60 61 62 63 64 65 66 67 68 69]
[70 71 72 73 74 75 76 77 78 79]
[80 81 82 83 84 85 86 87 88 89]
[90 91 92 93 94 95 96 97 98 99]]
"""
print(arr2.shape) # (10, 10)
- 若x和y中有一个指定为了-1,则具体的形状会根据填了具体数值的进行自动推算。(x和y不能同时指定为-1) ```python import numpy as np
arr = np.arange(100) arr1 = arr.reshape(10, -1) print(arr1) “”” 运行结果: [[ 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] [30 31 32 33 34 35 36 37 38 39] [40 41 42 43 44 45 46 47 48 49] [50 51 52 53 54 55 56 57 58 59] [60 61 62 63 64 65 66 67 68 69] [70 71 72 73 74 75 76 77 78 79] [80 81 82 83 84 85 86 87 88 89] [90 91 92 93 94 95 96 97 98 99]] “””
arr2 = arr.reshape(-1, 20) print(arr2) “”” 运行结果: [[ 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 30 31 32 33 34 35 36 37 38 39] [40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59] [60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79] [80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99]] “””
<a name="eYEka"></a>
### 1.4 数组的索引和切片
<a name="UbEl4"></a>
#### 1.4.1 数组的索引
- 数组的索引与列表的索引基本一致。
```python
import numpy as np
arr = np.arange(10)
print(arr) # [0 1 2 3 4 5 6 7 8 9]
print(arr[3]) # 3
print(arr[6:9]) # [6 7 8]
1.4.2 数组的切片
- 对于一个一维数组而言,其切片在操作上与列表没有什么区别。 ```python import numpy as np
arr = np.arange(10) print(arr[5:8]) # [5 6 7]
- 而对于二维数组而言,数组的切片不同于列表。列表只能在横方向上切片,而数组在横方向和纵方向上都可以切片。
- 示例:取arr1横方向上的[3, 8]步长为2,纵方向上的[0, 10]步长为3。
```python
import numpy as np
arr1 = np.arange(100).reshape(10, 10)
arr2 = arr1[3:8:2, 0:10:3]
print(arr2)
"""
运行结果:
[[30 33 36 39]
[50 53 56 59]
[70 73 76 79]]
"""
- 数组中特有的操作:arr[:]代表的是arr中所有的元素,会以此遍历arr中所有的元素并进行指定操作。
- 如:将arr中所有的元素加一。 ```python import numpy as np
arr = np.arange(10) print(arr) # [0 1 2 3 4 5 6 7 8 9]
arr[:] += 1 print(arr) # [ 1 2 3 4 5 6 7 8 9 10]
<a name="CsgSB"></a>
#### 1.4.3 数组切片的重要注意点
- 列表中切片是从原列表中拷贝[start, end)的数据给一块新的内存空间,因此对切片后的数据进行操作不会影响到原来的数据。
```python
lst = [x for x in range(10)]
lst_slice = lst[5:8]
lst_slice[1] = 999
print(lst) # [0, 1, 2, 3, 4, 5, 6, 7, 8, 9]
print(lst_slice) # [5, 999, 7]
- 而数组则是将切片的那部分内存地址给到新的变量,因此对切片后的数据进行操作会影响原有的数组。 ```python import numpy as np
arr = np.arange(10) print(arr) # [0 1 2 3 4 5 6 7 8 9]
arr_slice = arr[5:8] arr_slice[1] = 999
print(arr_slice) # [ 5 999 7] print(arr) # [ 0 1 2 3 4 5 999 7 8 9]
<a name="UAx5o"></a>
### 1.5 数组元素的筛选
<a name="PtEjP"></a>
#### 1.5.1 逻辑筛选
- 可以直接对array进行一个逻辑运算,它会自动对数组中的元素进行计算,并返回一个新的数组,其他包含每个元素逻辑运算的结果。
- 示例:判断一个数组中哪些元素是偶数,哪些不是:
```python
import numpy as np
arr1 = np.array([7, 1, 4, 5, 2])
arr2 = arr1 % 2 == 0
print(arr2) # [False False True False True]
- 接着将数据数组与布尔数组合并即可实现过滤。
- 过滤规则:将True对应的数据留下(符合条件的数据);将False对应的数据删除(不符合条件的数据)
示例:过滤出arr1中所有的偶数。
arr3 = arr1[arr2]
print(arr3) # [4 2]
1.5.2 条件筛选
示例:现有一个名字数组与成绩数组(【语、数、英、科】与90分的正负值),成员与成绩是按照索引位对应的。
name = ['Bob', 'Will', 'Bob', 'Joe']
grade = [[-3, 2, 0, -1], [1, 2, 3, -4], [2.5, 1.7, -0.2, 1], [-8, -4, 9, 10]]
- 要求:输入Bob的四门课成绩数据以及英语科学的数据。 ```python import numpy as np
列表数据
name = [‘Bob’, ‘Will’, ‘Jack’, ‘Joe’] grade = [[-3, 2, 0, -1], [1, 2, 3, -4], [2.5, 1.7, -0.2, 1], [-8, -4, 9, 10]]
封装成数组
name_arr = np.array(name, dtype=str) grade_arr = np.array(grade, dtype=float)
筛选出Bob的全科成绩(逻辑筛选)
print(grade_arr[name_arr == ‘Bob’]) # [[-3. 2. 0. -1.]]
筛选出Bob的全科成绩(逻辑筛选 + 纵向切片)
print(grade_arr[name_arr == ‘Bob’, 2:]) # [[ 0. -1.]]
<a name="fsvE6"></a>
#### 1.5.3 筛选练习
- 现有列表:`lst = [1, 'A', 2, 'B', 3, 'A', 4, 'B', 5, 'A', 6, 'B']`
- 将其转换为六行两列的数组,并筛选出A的数据。
- 代码实现:
- 导入NumPy库。
```python
import numpy as np
- 将列表数据转换为矩阵数据。 ```python lst = [1, ‘A’, 2, ‘B’, 3, ‘A’, 4, ‘B’, 5, ‘A’, 6, ‘B’] matrix_data = np.array(lst).reshape(6, 2) print(matrix_data)
“”” 运行结果: [[‘1’ ‘A’] [‘2’ ‘B’] [‘3’ ‘A’] [‘4’ ‘B’] [‘5’ ‘A’] [‘6’ ‘B’]] “””
- 判断纵方向上1号索引位上的元素是否为A。
```python
screening_criteria = matrix_data[::, 1] == 'A'
print(screening_criteria) # [ True False True False True False]
- 过滤出最终数据。 ```python final_data = matrix_data[screening_criteria] print(final_data)
“”” 运行结果: [[‘1’ ‘A’] [‘3’ ‘A’] [‘5’ ‘A’]] “””
<a name="FjDWd"></a>
### 1.6 一些内置的统计方法
<a name="VOfSs"></a>
#### 1.6.1 mean()
- mean()函数用于求数组中元素的平均值。
```python
import numpy as np
arr = np.arange(10)
avg = arr.mean()
print(avg) # 4.5
1.6.2 sum()
- sum()函数用于对数组内所有元素求和。 ```python import numpy as np
arr = np.arange(10) all = arr.sum() print(all) # 45
<a name="emu1R"></a>
#### 1.6.3 max()/min()
- max()函数用于对数组内所有元素求最大值。
- min()函数用于对数组内所有元素求最小值。
```python
import numpy as np
arr = np.arange(10)
print(arr.max()) # 9
print(arr.min()) # 0
1.6.4 axis属性
- axis可以按照行或列进行分组,再进行统计计算。
- axis=0:按列进行分组计算。
- axis=1:按行进行分组计算。
- 示例:计算arr每一行的总和与最大值,以及每一列的平均值与最小值。 ```python import numpy as np
arr = np.arange(25).reshape(5, -1)
print(arr.sum(axis=1)) # [ 10 35 60 85 110] print(arr.max(axis=1)) # [ 4 9 14 19 24]
print(arr.mean(axis=0)) # [10. 11. 12. 13. 14.] print(arr.min(axis=0)) # [0 1 2 3 4]
- axis没有缺省值,如果不指定就不会触发分组,而是将所有数据直接触发统计计算。
<a name="GFnhE"></a>
### 1.7 数组转置
- 数组转置通过属性T实现。
```python
import numpy as np
arr = np.arange(1, 10).reshape(3, -1)
print(arr)
"""
[[1 2 3]
[4 5 6]
[7 8 9]]
"""
print(arr.T)
"""
[[1 4 7]
[2 5 8]
[3 6 9]]
"""
02. Pandas
2.1 NumPy库的概述与安装
2.1.1 NumPy概述
- Pandas全名Python Data Analysis Library,是基于NumPy的一种工具,还可以结合matplotlib来使用。该工具是为了解决数据分析任务而创建的。
- Pandas纳入了大量库和一些标准的数据模型,提供了高效地操作大型数据集所需的工具。
- Pandas提供了诸多的数据处理方法和时间序列的操作方法,是当下最重要的Python科学运算模块之一。
- Pandas提供了大量能使我们快速便捷地处理数据的函数和方法,比如数据读取,索引切分,分组,时间序列,重塑,合并。
- 对各类数据读取,包括csv,json,excel,txt,api,html,数据库等等;可以把数据高效简单存储成多种格式,包括hdfs,csv,excel等。
Pandas中最重要的两个数据结构是DataFrame和Series,可以对数据进行简单的处理。
2.1.2 安装Pandas
pip install pandas
2.2 Series序列
2.2.1 序列的概述与创建
Series是Pandas中的数据结构之一,是一种类似于维数组的对象,由一组数据以及一组与之相关的数据标签(即索引组成)
- Series可以通过Pandas库中的Series()方法生成。
- 数据前面的0、1、2、3、4就是数据标签。 ```python import pandas as pd
lst = [5, 1, 3, 7, 2] se = pd.Series(lst) print(se)
“”” 运行结果: 0 5 1 1 2 3 3 7 4 2 dtype: int64 “””
- 可以通过index属性为数据自定义数据标签。(数据标签是可以重复的,后面的标签不会覆盖前面的标签)
```python
import pandas as pd
se = pd.Series(
[5, 1, 3, 7, 2, 6],
index=['a', 'b', 'c', 'd', 'a', 'c']
)
print(se)
"""
运行结果:
a 5
b 1
c 3
d 7
a 2
c 6
dtype: int64
"""
2.2.2 序列的索引
- 序列中的值可以通过“序列名[“数据标签”]”获取。
- 假如一个数据标签只对应一个数据,那么会直接获取到这个数据。 ```python import pandas as pd
se = pd.Series([5, 1, 3, 4, 6], [‘a’, ‘b’, ‘c’, ‘d’, ‘e’]) print(se[‘c’]) # 3
- 假如一个数据标签对应多个数据,那么会返回包含这个数据序列对应的所有数据的新序列。
```python
import pandas as pd
se = pd.Series([5, 1, 3, 4, 6], ['a', 'b', 'c', 'a', 'c'])
print(se['a'])
"""
运行结果:
a 5
a 4
dtype: int64
"""
- 除此之外,还可以用iloc[index]函数通过索引位来获取元素。 ```python import pandas as pd
se = pd.Series([5, 1, 3, 4, 6]) print(se.iloc[3]) # 4
- <br />
- <br />
- <br />
- <br />
- <br />
- <br />
- <br />
- <br />
- <br />
- 汇总统计:
- 5出现2次,3出现2次,1出现两次。
```python
import pandas as pd
se = pd.Series([5, 5, 3, 3, 2])
print(se.value_counts())
"""
运行结果:
5 2
3 2
2 1
dtype: int64
"""
- 方式二: ```python import pandas as pd from collections import Counter
se = pd.Series([5, 5, 3, 3, 2]) print(Counter(se)) # Counter({5: 2, 3: 2, 2: 1}) ```