2020,努力做一个无可替代的人!
写在前面的话
NumPy 第三小节,同学们自行复习第一二小节:
疫情严峻,有空多学习,没事多看看文章,期待阳春三月!高阶部分篇篇都是干货
,建议大家不要错过任何一节内容,最好关注我,方便看到每次的文章推送。
正文
前面在创建 NumPy 数组的时候,通过创建方法可以发现有些类似于线性代数,比如创建的正态分布数组、对角数组等,也确实是这样,矩阵的一些特性 NumPy 同样具有。
先来看一下四则运算:
创建维度相同的两个数组,数组1的值分别为0-5,数组2是一个全1数组
# 创建 2行3列的二维数组
data_arr1 = np.arange(6).reshape(2, 3)
# 输出
[[0 1 2]
[3 4 5]]
# 创建 2行3列的全1数组
data_ones = np.ones((2, 3), dtype=np.int)
# 输出
[[1 1 1]
[1 1 1]]
ok,数组创建完毕,试着进行计算
# 数组加法运算
data_arr1 + data_ones
# 输出
[[1 2 3]
[4 5 6]]
# 数组除法运算
data_ones / (data_arr1 + data_ones)
# 输出
[[1. 0.5 0.33333333]
[0.25 0.2 0.16666667]]
和我们实际进行数组计算的一致,数组之间的任何算术运算都会应用到元素级。
但是,这个前提是两个数组的维度一致,如果,不一致?或者是个数呢?
看例子:
# 数组与标量的算术运算
data_arr1 * 5
# 输出
[[ 0 5 10]
[15 20 25]]
同样,数组与标量的算术运算也会将标量的值传播到各个元素。
不同大小数组之间的运算叫做广播。暂且不解释,我们下节专门说它。
再来看下矩阵运算
在线性代数中,有矩阵转置,在 NumPy 中,也就有了数组转置。
转置(transpose)是一种数组维度重塑的一种特殊形式,它返回的是源数据的视图。
数组不仅有 transpose 方法,还有一个特殊的 T 属性。
data_arr1
# 输出
[[0 1 2]
[3 4 5]]
# 转置操作的两种实现方法
data_arr1.T
data_arr1.transpose()
# 输出
[[0 3]
[1 4]
[2 5]]
在进行矩阵运算时,比如我们需要计算矩阵内积:X[^T]X,可以使用 np.dot 计算
根据公式:矩阵内积 = X 的转置乘以 X
# 创建数组
data_arr2 = np.random.randn(1,3)
# 输出
[[-0.14205835 -1.43319166 0.8389062 ]]
# 计算矩阵内积
np.dot(data_arr2.T, data_arr2)
# 输出
[[ 0.02018058 0.20359685 -0.11917363]
[ 0.20359685 2.05403832 -1.20231337]
[-0.11917363 -1.20231337 0.70376361]]
还有高维数组的转置这些,实际上并不常用,而且也不是很好理解,就不再提了,最常用的就是二维数组的转置,会这个就可。
列举部分线性代数在 NumPy 的实现
函数 | 说明 |
---|---|
dot | 矩阵乘法 |
trace | 计算对角线元素的和 |
det | 计算矩阵行列式 |
inv | 计算方阵的逆 |
solve | 解线性方程组 Ax = b,其中 A 为一个方阵 |
lstsq | 计算 Ax = b 的最小二乘解 |
… | … |
通用函数
通用函数(即 ufunc)是一种对 ndarray 中的数据执行元素级运算的函数。
你可以将其看做简单函数的矢量化包装器:接受一个或多个标量值,并产生一个或多个标量值。
先来看看一元通用函数(unary ufunc)
# 创建数组
data_unary = np.arange(10)
# 输出
[0 1 2 3 4 5 6 7 8 9]
# 求数组每个元素的平方根
np.sqrt(data_unary)
# 输出
[0. 1. 1.41421356 1.73205081 2. 2.23606798
2.44948974 2.64575131 2.82842712 3. ]
# 求数组的最大最小值
np.min(data_unary)
np.max(data_unary)
# 输出
0
9
就和 Python 的常规语法一样,NumPy 通用函数也是直接调用即可。
另外还有一些接受2个数组,返回一个结果数组的通用函数(二元函数)
列举一些常用的一元和二元函数
函数 | 说明 | |
---|---|---|
一元函数 | abs | 计算整数、浮点数或负数的绝对值。 |
一元函数 | sqrt | 计算个元素的平方根 |
一元函数 | square | 计算各元素的平凡 |
一元函数 | exp | 计算各元素的指数 |
一元函数 | log、log10、log2 | 分别为底数为e的log、底数为10的log、底数为2的log |
一元函数 | sign | 计算各元素的正负号 |
一元函数 | ceil | 计算各元素的ceiling值(大于等于该值的最小整数) |
一元函数 | floor | 计算各元素的floor值(小于等于该值的最大整数) |
一元函数 | cos、cosh、sin、sinh、tan、tanh | 普通和双曲线三角函数 |
一元函数 | isnan | 返回一个数组表示”哪些是NaN“的布尔型数组 |
… | … | … |
二元函数 | add | 将数组中对应的元素相加 |
二元函数 | sutract | 从第一个数组中减去第二个数组中的元素 |
二元函数 | multiply | 数组元素相乘 |
二元函数 | divide | 数组元素相除 |
二元函数 | power | 计算 A 的 B 次方 |
… | … | … |
是不是以为到这就结束了?
没错,快结束了,但是我总觉得下面的内容才是今天的重点内容
,信不信由你。
条件逻辑表述
我们都知道 Python 中的三元表达式: x if condition else y
那如果我们有两个值数组分别表示 x 和 y,有一个布尔数组表示 condition,如何进行条件逻辑表述呢?
# 创建数组
data_xarr = np.array([1, 2, 3, 4, 5])
data_yarr = np.array([-1, -2, -3, -4, -5])
data_tag = np.array([True, False, False, False, True])
根据布尔数组 data_tag 选取 data_xarr 和 data_yarr 的值:当 data_tag 为 True,选择 data_xarr 的值,否则从 data_yarr 中选取。
先来看一下列表推导式:
# 实现三元表达式功能
result = [(x if tag else y)
for x, y, tag in zip(data_xarr, data_yarr, data_tag)
]
# 输出
[1, -2, -3, -4, 5]
是不是很麻烦?
NumPy 中一个函数就可以实现上面的功能!!!
# 使用 where 函数实现三元表达式功能
result = np.where(data_tag, data_xarr, data_yarr)
# 输出
[ 1 -2 -3 -4 5]
是不是很方便?
解释一下 where 函数的用法:第一个参数是条件 condition,第二和第三个参数相当于三元表达式中的 x 和 y
。其中 x 和 y 不必是数组,也可以是标量值, where 函数返回一个新的数组。
例如,通过 where 函数进行数据清洗,大于0的数全部置为1,小于0的数全部置为-1
# 创建 3*3 的数组
data_warr = np.random.randn(3, 3)
# 输出
[[-0.57519374 0.91571952 0.2104197 ]
[ 0.32693672 0.95512399 -0.09581747]
[-1.40553911 -0.96782964 0.73291699]]
# 大于0的数全部置为1,小于0的数全部置为-1
result = np.where(data_warr>0, 1, -1)
# 输出
[[-1 1 1]
[ 1 1 -1]
[-1 -1 1]]
如果要保留小于0的数组值,只替换大于0的值呢?
# 保留小于0的数组值,只替换大于0的值
np.where(data_warr>0, 1, data_warr)
# 输出
[[-0.57519374 1. 1. ]
[ 1. 1. -0.09581747]
[-1.40553911 -0.96782964 1. ]]
比 where 更重要的内容
布尔判断+统计
,你没听错,数据分析常用噢
举例:随机数中所有大于0的数的和、平均值、标准差方差等
# 创建10个范围在-10~10的随机整数
data_rn = np.random.randint(-10, 10, 10)
# 输出
[-9 -2 -1 -7 9 9 -4 6 3 -1]
# 大于0的所有数的和、平均值、标准差方差
(data_rn>0).sum()
(data_rn>0).mean()
(data_rn>0).std()
(data_rn>0).var()
# 输出
4
0.4
0.48989794855663565
0.24000000000000005
any、how 检测
any 用于测试数组中是否存在一个或多个 True
all 用于检查数组中所有值是否都是 True
sort 排序
和 Python 内置的列表类型一样,NumPy 数组也可以通过 sort 方法进行排序
data_sort = np.array([[1, 0, -2, 5, 4], [-1, -3, 3, 4, 2]])
# 输出
[[ 1 0 -2 5 4]
[-1 -3 3 4 2]]
# 默认排序(行)
data_sort.sort()
# 输出
[[-2 0 1 4 5]
[-3 -1 2 3 4]]
# 在0轴上排序(列)
data_sort.sort(axis=0)
# 输出
[[-3 -1 1 3 4]
[-2 0 2 4 5]]
unique 唯一化
针对一维数组最常用的基本集合运算:unique 用于找出数组中的唯一值并返回已排序的结果
# `unique 找出数组中的唯一值并返回已排序的结果`
data_ints = np.array([2, 3, 1, 1, 2, 4, 6, 7, -1])
np.unique(data_ints)
# 输出
[-1 1 2 3 4 6 7]
呼呼,没骗你吧,这才是最实用的内容。
总结一下:
说实话,今天的内容挺多的。
总结一下:
- NumPy 数组的四则运算
- NumPy 数组的矩阵运算
- 条件逻辑表述 where
- 布尔判断、统计、排序、唯一化
前两小节属于运算中比较基础的内容,知道是什么、怎么用就可以了。
重点是后面两小节,在实际项目中用处很大,建议大家看着例子多读几篇。
可以的话,在自己电脑上运行一遍试试
写在后面的话
透个底,NumPy 系列在我的计划中还有最后一篇,今天是第三篇。
不知道大家学的怎么样,有的内容了解就行,也没必要死磕下去。
当然,我标重点还是建议都掌握啦,下期见!
碎碎念一下
最全的干货已经开始了,大家不要掉队啊。
建议大家关注我,不要错过高阶部分内容!!!
原创不易,欢迎点赞噢
文章首发:公众号【知秋小梦】
文章同步:掘金,简书