3.Numpy
引入Numpy的目的
- 为何不直接用list?
- 慢
- 缺少数学操作
heights = [1.73, 1.68, 1.71, 1.89, 1.79] # 5人的身高
weights = [65.4, 59.2, 63.6, 88.4, 68.7] # 5人的体重
bmis = weights / heights ** 2 # 却不能直接计算5人的BMI
import numpy as np
np_heights = np.array(heights) # array,向量,通常只包含数值
np_weights = np.array(weights)
bmis = np_weights / np_heights ** 2 # 这里计算的单元是一个向量
bmis
运行结果如下:
array([21.85171573, 20.97505669, 21.75028214, 24.7473475 , 21.44127836])
更新BMI公式,现在是对向量做计算
\begin{equation}\vec{BMIS} = \frac{\vec{weights}}{\vec{heights}^{2}}\end{equation}
bmis > 21 # 符合直觉的结果, array([ True, False, True, True, True])
round(bmis) # 只有numpy.ndarray支持的方法 报错
np.round(bmis) # 需要使用np重载的方法
# array([22., 21., 22., 25., 21.])
np.round(bmis,1) # 需要使用np重载的方法
array([21.9, 21. , 21.8, 24.7, 21.4])
np.max(bmis) == max(bmis) # 大胆地猜想这两种方法应该都可以
help(np.ndarray) # 文档即教程
type(np_weights) # 应该返回numpy的类型 numpy.ndarray
mixed_list = [1.0, "is", True] # 通用类型的list
type(np.array(mixed_list)) # 转化为numpy array numpy.ndarray
np.array(mixed_list) # 数据类型是字符串 array(['1.0', 'is', 'True'], dtype='<U32')
深入了解numpy数据类型
数理统计和线性代数基础
数理统计的例子
- 在大样本数据上计算身高体重指数
- 把前面5人的例子扩大1000倍
- 随机产生一个正态分布
中国成年人身高,体重均值和标准差的参考值 (2015)
性别 | 东北华北 | 西北 | 东南 | 华中 | 华南 | 西南 |
---|---|---|---|---|---|---|
身高,体重 | 均值,标准差 | 均值,标准差 | 均值,标准差 | 均值,标准差 | 均值,标准差 | 均值,标准差 |
男(mm) | 1693, 56.6 | 1684, 53.7 | 1686, 55,2 | 1669, 56.3 | 1650, 57.1 | 1647, 56.7 |
女(mm) | 1586, 51.8 | 1575, 51.9 | 1575, 50.8 | 1560, 50.7 | 1549, 49.7 | 1546, 53.9 |
男(kg) | 64, 8.2 | 60, 7.6 | 59, 7.7 | 57, 6.9 | 56, 6.9 | 55, 6.8 |
女(kg) | 55, 7.1 | 52, 7.1 | 51, 7.2 | 50, 6.8 | 49, 6.5 | 50, 6.9 |
选择东南地区成年男性数据:身高:1686, 55.2,体重:59, 7.7
height_5k = np.random.normal(1.686, 0.0552, 5000) # 5000身高数据
weight_5k = np.random.normal(59, 7.7, 5000) # 5000体重数据
shmale_5k = np.column_stack((height_5k, weight_5k)) # 5000上海男性数据
shmale_5k # 随机产生一些瘦子和胖子
返回结果如下:
array([[ 1.71673326, 59.30856039],
[ 1.78173268, 53.59941495],
[ 1.63402604, 76.34316629],
...,
[ 1.82961841, 53.30531369],
[ 1.64105013, 60.11390686],
[ 1.70708758, 66.51344072]])
shmale_weight = shmale_5k[:,1]
shmale_height = shmale_5k[:,0]
shmale_height_mean = np.mean(shmale_height) # 身高均值
shmale_height_std = np.std(shmale_height) # 身高标准差
shmale_weight_mean = np.mean(shmale_weight) # 体重均值
shmale_weight_std = np.std(shmale_weight) # 体重标准差
from tabulate import tabulate # 格式化成表格样式
print(tabulate([['身高(米)', shmale_height_mean, shmale_height_std],
['体重(公斤)', shmale_weight_mean, shmale_weight_std]],
headers=['上海男','均值', '标准差']))
运行结果示例:
上海男 均值 标准差
------------ -------- ---------
身高(米) 1.68597 0.0548796
体重(公斤) 59.1071 7.75585
shmale_bmi = shmale_weight / shmale_height ** 2 # 计算5000身高体重指数
shmale_bmi
print(np.mean(shmale_bmi), np.std(shmale_bmi)) # 上海男性体型分布
线性代数例子
-
解方程组 $\begin{bmatrix}2x + 3y = 8 \end{bmatrix}$ $\begin{bmatrix}5x + 2y = 9 \end{bmatrix}$
-
用矩阵的形式表示为 $$ A = \begin{bmatrix}2 & 3\5 & 2\end{bmatrix} ;;;; \vec{b} = \begin{bmatrix}8\9\end{bmatrix}$$
-
目标是求向量x $$ A\vec{x}= \vec{b} $$
a = np.array([[2, 3], [5, 2]]) # 方程组系数矩阵
a.transpose() # 转置
转置后结果如下:
b = np.array([8, 9])
print(b.shape, a.shape) # shape不是函数,是tuple
b.transpose()
运行结果如下:
(2,) (2, 2)
array([8, 9])
矩阵的索引
print(tabulate([['0', a[0,0], a[0,1]],
['1', a[1,0], a[1,1]]],
headers=['A', '0', '1']))
运行结果如下:
A 0 1
--- --- ---
0 2 3
1 5 2
矩阵运算文档
![]()
# 矩阵求逆
from numpy.linalg import inv as inv
a_inv = inv(a)
a_inv
运行结果如下:
array([[-0.18181818, 0.27272727],
[ 0.45454545, -0.18181818]])
$$ A^{-1}A=\begin{bmatrix}1 & 0\0 & 1\end{bmatrix} $$
np.round(a_inv @ a) # 逆矩阵和原矩阵乘来验证求逆, @代表矩阵乘
运行结果如下:
array([[ 1., 0.],
[-0., 1.]])
$$ A^{-1}A\vec{x}=A^{-1}\vec{b}$$
$$ \begin{bmatrix}1 & 0\0 & 1\end{bmatrix}\vec{x}= A^{-1}\vec{b}$$
$$ \vec{x} = A^{-1}\vec{b}$$
x = a_inv @ b
x
运行结果如下:
array([1., 2.])
方程组求解:
from numpy.linalg import solve as solve # 引入求解方法
solve(a, b)
运行结果如下:
array([1., 2.])
$$ \vec{x} = \begin{bmatrix}1\2\end{bmatrix} $$
$$ x=1 $$ $$ y=2 $$