二、通用函数:快速的逐元素数组函数
通用函数,也可以称为ufunc,是一种在ndarray数据中进行逐元素操作的函数。某些简单函数接收一个或多个标量数据,并产生一个或多个标量结果,而通用函数就是对这些简单函数的向量化封装。而通用函数又分为一元通用函数和二元通用函数。下表则为一元通用函数:
函数名 | 描述 |
---|---|
abs、fabs | 逐元素地计算整数、浮点数或复数的绝对值 |
sqrt | 计算每个元素的平方根 |
aquare | 计算每个元素的平方 |
exp | 计算每个元素的自然指数值e^x |
log、log10、log2、log1p | 分别对应:自然对数(e为底)、对数10为底、对数2为底、log(1+x) |
sign | 计算每个元素的符号值:1(正数)、0(0) |
ceil | 计算每个元素的最高整数值(即大于等于给定数值的最小整数) |
floor | 计算每个元素的最小整数值(即小于等于给定数值的最大整数) |
rint | 将元素保留到整数位,并保持dtype |
modf | 分别将数组的小数部分和整数部分按数组形式返回 |
isnan | 返回数组中的元素是否是一个NaN(不是一个数值),形式为布尔值数组 |
isfinite、isinf | 分别返回数组中的元素是否有限(非inf、非NaN)、是否无限的,形式为布尔值数组 |
cos、cosh、sin、sinh、tan、tanh | 常规的双曲三角函数 |
arccos、arccosh、arcsin、arcsinh、arctan、arctanh | 反三角函数 |
logical_not | 对数组的元素按位取反 |
我们可以拿sqrt和exp函数进行演示:
arr = np.arange(10)
print(arr)
arr1 = np.sqrt(arr)
print(arr1)
arr1 = np.exp(arr)
print(arr1)
------------------------------------------------------------
[0 1 2 3 4 5 6 7 8 9]
[0. 1. 1.41421356 1.73205081 2. 2.23606798
2.44948974 2.64575131 2.82842712 3. ]
[1.00000000e+00 2.71828183e+00 7.38905610e+00 2.00855369e+01
5.45981500e+01 1.48413159e+02 4.03428793e+02 1.09663316e+03
2.98095799e+03 8.10308393e+03]
而二元通用函数就如下表所示:
函数名 | 描述 |
---|---|
add | 将数组的对应元素相加 |
subtract | 在第二个数组中,将第一个数组中包含的元素去除 |
multiply | 将数组的对应元素相乘 |
divide、floor_divide | 除或整除 |
power | 将第二个数组的元素作为第一个数组对应元素的幂次方 |
maximum、fmax | 逐个元素计算最大值,fmax忽略NaN |
minium、fmin | 逐个元素计算最小值,fmin忽略NaN |
mod | 按元素的求模计算(即求除法的余数) |
copysign | 将第一个数组的符号值改为第二个数组的符号值 |
greater、greater_equal、less、less_equal、equal、not_equal | 进行逐个元素的比较,返回布尔值数组(与数学操作符>、>=、<、<=、==、!= 效果一致) |
logical_and、logical_or、logical_xor | 进行逐个元素的逻辑操作(与逻辑操作符&、|、^效果一致) |
比如add或maximum 则会选择接收两个数组并返回一个数组作为结果,因此称为二元通用函数:
x = np.random.randn(8)
y = np.random.randn(8)
print(x)
print(y)
arr = np.maximum(x,y)
print(arr)
------------------------------------------------------------
[-1.03902844 -0.21599975 1.64308697 -0.56306956 1.34655616 -0.58567114
0.66120554 0.31227188]
[ 0.36550034 0.66029402 -1.13949199 -2.38142943 -0.13830131 -1.13303299
1.08826205 -0.89039793]
[ 0.36550034 0.66029402 1.64308697 -0.56306956 1.34655616 -0.58567114
1.08826205 0.31227188]
注意modf要用两个数组去接,一个作为整数部分,另一个作为小数部分。
arr = np.random.randn(7)*5
print(arr)
x,z = np.modf(arr)
print(x)
print(z)
------------------------------------------------------------
[ 6.1484688 -3.82240789 -9.50884485 -1.99455458 -0.43966779 -5.7158038
-0.29702221]
[ 0.1484688 -0.82240789 -0.50884485 -0.99455458 -0.43966779 -0.7158038
-0.29702221]
[ 6. -3. -9. -1. -0. -5. -0.]
三、使用数组进行面向数组编程
利用数组表达式来替代显示循环的方法,称为向量化。通常,向量化的数组操作会比纯Python的等价实现在速度上快一到两个数量级(甚至更多),这对所有种类的数值计算会产生最大的影响。
3.1 将条件逻辑作为数组操作
假设我们有一个布尔值数组和两个数值数组.假设我们要实现cond中的元素为True时,我们取xarr中的对应元素值,否则取yarr中的元素。此时我们可以使用np.where来实现。
xarr = np.array([1.1, 1.2, 1.3, 1.4, 1.5])
yarr = np.array([2.1, 2.2, 2.3, 2.4, 2.5])
cond = np.array([True, False, True, True, False])
result = np.where(cond,xarr,yarr)
print(result)
------------------------------------------------------------
[1.1 2.2 1.3 1.4 2.5]
np.where的第二个和第三个参数并不需要是数组,它们可以是标量。where在数据分析中的一个典型用法是根据一个数组来生成一个新的数组。假设你有一个随机生成的矩阵数据,并且你想将其中的正值都替换为2,将所有负值替换为-2,使用np.where会很容易实现。
arr = np.random.randn(4,4)
print(arr)
arr1 = np.where(arr>0,2,-2)
print(arr1)
------------------------------------------------------------
[[ 0.59441776 1.0285962 -0.98295918 -0.59805263]
[ 2.06504551 -0.09564743 0.71709217 1.70395227]
[-0.70121399 -1.42769854 -0.14439175 0.9077478 ]
[ 0.27645334 0.2326139 -1.33845457 -1.4110736 ]]
[[ 2 2 -2 -2]
[ 2 -2 2 2]
[-2 -2 -2 2]
[ 2 2 -2 -2]]
import numpy as np
import pandas as pd
import matplotlib.pyplot as plt
import seaborn as sns
import warnings
warnings.filterwarnings('ignore')
import ssl
ssl._create_default_https_context = ssl._create_unverified_context
3.2 数学和统计方法
许多关于计算整个数组统计值或关于轴向数据的数学函数,可以作为数组类型的方法被调用。基础数组统计方法如下表所示。
函数 | 描述 |
---|---|
sum | 沿着轴向计算所有元素的累加和 |
mean | 数学平均,0长度的数组平均值为NaN |
std,var | 标准差和方差,可以选择自由度调整(默认分母是0) |
min,max | 最小值和最大值 |
argmin,argmax | 最小值和最大值的位置 |
cumsum | 从0开始元素累积和 |
cumprod | 从1开始元素累积积 |
比如sum、mean和std既可以直接调用数组实例的方法,也可以使用顶层的NumPy函数。
arr = np.random.randn(5,4)
print(arr)
arr1 = arr.mean()
print(arr1)
arr1 = np.mean(arr)
print(arr1)
arr1 = arr.sum()
print(arr1)
------------------------------------------------------------
[[-0.65647657 -2.56698731 -1.23244024 -0.05458049]
[ 0.25584376 0.22427777 -0.05331641 0.73508303]
[ 1.03766921 1.15232246 -1.65808877 -1.05891814]
[ 1.2800827 -0.72958169 0.60202623 2.30581143]
[ 0.03996198 -0.75069021 -0.45835264 -0.77543839]]
-0.11808961401172569
-0.11808961401172569
-2.3617922802345137
像mean、sum等函数可以接收一个可选参数axis,这个参数可以用于计算给定轴向上的统计值,形成一个下降一维度的数组。当axis=1时,是计算每一行的值,axis=0时,是计算每一列的值。
arr1 = arr.mean(axis=1)
print(arr1)
arr1 = arr.mean(axis=0)
print(arr1)
------------------------------------------------------------
[-1.12762115 0.29047204 -0.13175381 0.86458467 -0.48612982]
[ 0.39141622 -0.5341318 -0.56003436 0.23039149]
其他方法里,例如cumsum和cumprod并不会聚合,它们会产生一个中间结果。在多维数组中,像cumsum这样的累积函数返回相同长度的数组。
arr = np.array([[1,2,3],[4,5,6],[7,8,9]])
print(arr)
arr1 = arr.cumsum(axis=0)
print(arr1)
arr1 = arr.cumprod(axis=1)
print(arr1)
------------------------------------------------------------
[[1 2 3]
[4 5 6]
[7 8 9]]
[[ 1 2 3]
[ 5 7 9]
[12 15 18]]
[[ 1 2 6]
[ 4 20 120]
[ 7 56 504]]
3.3 布尔值数组的方法
sum通常可以用于计算布尔数组中的True个数:
arr=np.random.randn(10)
print(arr)
arr1 = (arr>0).sum()
print(arr1)
------------------------------------------------------------
[-0.83867513 1.18896642 -1.71248171 -0.27443706 -0.3342982 -0.39523821
-1.24415858 1.34498155 0.65944045 0.25324057]
4
对于布尔值数组,有两个非常有用的方法any和all。any检查数组中是否至少有一个True,而all检查是否每个值都是True:
bools = np.array([False, False, True, False])
arr = bools.any()
print(arr)
arr = bools.all()
print(arr)
------------------------------------------------------------
True
False
3.4 排序
NumPy可以使用sort方法按位置排序:
arr = np.random.randn(6)
print(arr)
arr.sort()
print(arr)
------------------------------------------------------------
[ 0.56565982 -2.20081556 -0.50203145 1.17931186 -0.12006898 -0.86731374]
[-2.20081556 -0.86731374 -0.50203145 -0.12006898 0.56565982 1.17931186]
这里是对原数组按位置排序,而顶层的np.sort方法返回的是已经排序好的数组拷贝。
我们可以在多维数组中根据传递axis值,沿着轴向对每个一维数据段进行排序:
arr = np.random.randn(5,3)
print(arr)
arr.sort(1)
print(arr)
------------------------------------------------------------
[[ 1.14555612 0.74128658 0.47774248]
[-1.97954927 -1.29796415 0.91605363]
[ 1.26675142 -1.42665741 -0.14145892]
[ 0.61390236 1.25466866 1.53423606]
[-1.53613842 1.07414355 -0.40904382]]
[[ 0.47774248 0.74128658 1.14555612]
[-1.97954927 -1.29796415 0.91605363]
[-1.42665741 -0.14145892 1.26675142]
[ 0.61390236 1.25466866 1.53423606]
[-1.53613842 -0.40904382 1.07414355]]
3.5 唯一值与其他集合逻辑
NumPy包含一些针对一维ndarray的基础集合操作。常用的一个方法是np.unique,返回的是数组中唯一值排序后形成的数组:
ints = np.array([3,3,3,2,2,1,1,4,4])
arr = np.unique(ints)
print(arr)
------------------------------------------------------------
[1 2 3 4]
类似的其数组的集合操作如下表所示:
函数名 | 描述 |
---|---|
unique (x) | 计算x的唯一值,并排序 |
intersect1d(x,y) | 计算x和y的交集,并排序 |
union1d(x,y) | 计算x和y的并集,并排序 |
in1d(x,y) | 计算x中的元素是否包含在y中,返回一个布尔值数组 |
setdiff1d(x,y) | 差集,在x中但不在y中的x元素 |
setxor1d(x,y) | 异或集,在x或y中,但不属于x,y交集的元素 |
下班啦!!!!
生活本来就是不快乐的,所做的努力就是为了能够快乐,我努力寻找快乐,而不是为了努力生活。