python:NumPy基础(2),通用函数及数据处理

来源:互联网 发布:空气加湿器 知乎 编辑:程序博客网 时间:2024/05/16 17:58

利用python进行数据分析

第四章:NumPy基础:数组和矢量计算

通用函数:快速的元素级数组函数

通用函数(即ufunc)是一种对ndarray中的数据执行元素级运算的函数。可将其看做简单函数(接受一个或多个标量值,并产生一个或多个标量值)和矢量化包装器。
许多ufunc都是简单的元素级变体,如sqrt何exp:
>>> import numpy as np
>>> arr=np.arange(10)
>>> arr
array([0, 1, 2, 3, 4, 5, 6, 7, 8, 9])
>>> np.sqrt(arr)
array([ 0. , 1. , 1.41421356, 1.73205081, 2. ,
2.23606798, 2.44948974, 2.64575131, 2.82842712, 3. ])
>>> np.exp(arr)
array([ 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])
这些都是一元(unary)ufunc。另外一些(如add或maximum)接受2个数组(因此也叫二元(binary)ufunc),并返回一个结果数组:
>>> x=randn(8)
>>> y=randn(8)
>>> x+y
array([ 1.68094221, 0.42658988, 2.72688609, 1.70274258, 1.43604021, 1.2562558 , 2.16557412, 0.81580915])
>>> np.maximum(x, y)
array([ 1.99943165, 1.38437674, 1.52136131, 0.97030873, 0.76957974, 1.16327551, 2.35991155, 0.67526549])
但有些ufunc也可以返回多个数组。modf(),能够将数组中的整数和小数分开成两个数组,相当于python内置函数divmod的矢量化版本。
>>> arr=randn(7)*5
>>> arr
array([ 7.60937949, 1.31110658, 2.07687003, 3.85238617,
3.42094846, -1.9817143 , 10.73222908])
>>> np.modf(arr)
(array([ 0.60937949, 0.31110658, 0.07687003, 0.85238617, 0.42094846, -0.9817143 , 0.73222908]), array([ 7., 1., 2., 3., 3., -1., 10.]))

表4-3:一元ufunc
| 函数 | 说明 |
| abs、fabs | 计算整数、浮点数或复数的绝对值。对于非复数值,可以使用更快的fabs |
| sqrt | 计算各元素的平方根。相当于arr**0.5 |
| square | 计算各元素的平方。相当于arr**2 |
| exp | 计算各元素的指数e**x |
| log、log10、log2、log1p | 分别为自然对象(底数为e)、底数为10的log、底数为2的log、log(1+x) |
| sign | 计算各元素的正负号:1(整数)、0(零)、-1(负数) |
| ceil | 计算各元素的ceiling值,即大于等于该值的最小整数 |
| floor | 计算各元素的floor值,即小于等于该值的最大整数 |
| rint | 将各元素值四舍五入到最近的整数,保留dtype |
| modf | 将数组的小数和整数部分以两个独立数组的形式返回 |
| isnan | 返回一个表示“哪些值是NaN(缺失值)”的布尔型数组 |
| isfinite、isinf | 分别返回一个表示“哪些元素是有穷的(非inf,非Nan)”或“哪些元素是无穷的”的布尔型数组 |
| cos、cosh、sin、sinh、tan、tanh | 普通型和双曲型三角函数 |
| arccos、arccosh、arcsin、arcsinh、arctan、arctanh | 反三角函数 |
| logical_not | 计算各元素not x的真值。相当于-arr |

表4-4:二元ufunc
| 函数 | 说明 |
| add | 将数组中对应的元素相加 |
| subtract | 从第一个数组中减去第二个数组中的元素 |
| multiply | 数组元素相乘 |
| divide、floor_divide | 除法(divide)或向下圆整除法(丢弃余数(floor_divide)) |
| power | 对第一个数组中的元素A,根据第二个数组中的相应元素B,计算A**B |
| maximum、fmax | 比较两个数组,返回元素级的比较结果的最大值计算。fmax将忽略NaN |
| minimum、fmin | 比较两个数组,返回元素级的比较结果的最小值计算。fmin将忽略NaN |
| mod | 元素级的求模计算(除法的余数) |
| copysign | 将第二个数组中的值的符号(正负号)复制给第一个数组中的值 |
| greater、greater_equal、less、less_equal、equal、not_equal | 执行元素级的比较运算,最终产生布尔型数组。相当于运算符>、>=、<、<=、==、!= |
| logical_and、logical_or、logical_xor | 执行元素级的真值逻辑运算。相当于运算符&、|、^ |

1,利用数组进行数据处理

将条件逻辑表达为数组运算
numpy.where函数式三元表达式x if condition else y的矢量化版本,假设存在一个布尔数组和两个值数组:
>>> 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])
假设我们想要根据cond中的值选取xarr和yarr的值:当cond中的值为True时,选取xarr的值,否则从yarr中选取。(这也是我们常常想到的队列排序的一个模型)
列表推导式的写法如下:
>>> result=[(x if c else y) for x, y, c in zip(xarr, yarr, cond)]
>>> result
[1.1000000000000001, 2.2000000000000002, 1.3, 1.3999999999999999, 2.5]
如果利用这个表达式,则存在两个问题。第一个,它对大数组的处理速度很慢(因为所有工作都是由纯Python完成的)。第二,无法用于多维数组。
如果使用np.where,则可以将该功能写得非常简洁:
>>> result=np.where(cond, xarr, yarr)
>>> result
array([ 1.1, 2.2, 1.3, 1.4, 2.5])
np.where(condition,ndarray1,ndarray2) #第一个数值condition表示为判断条件,第二个数值ndarray1表示为数组1,第三个数值ndarray2表示为数组2。
np.where(condition,number1,number2) #第一个数值condition表示为判断条件,第二个数值number1表示为标量值1,第三个数值number2表示为标量值2。
np.where()第一个参数为判断条件,第二和第三个参数为数组或标量值
往往在实际分析工作中,np.where通常用于根据另一个数组而产生一个新的数组
假设有一个由随机数据组成的矩阵,你希望将所有正值替换为2,将所有负值替换为-2,利用np.where就很容易做到
>>> arr=randn(4, 4)
>>> arr
array([[ 0.06626892, 0.97654534, -0.03410723, 1.17214921],
[-2.36938123, 0.16360117, 0.23747205, 0.12226709],
[-0.15438514, 1.0935923 , 0.47175842, -1.70140082],
[-0.2854488 , 0.55628614, 0.54834081, -2.52706882]])
>>> np.where(arr>0,2,-2)
array([[ 2, 2, -2, 2],
[-2, 2, 2, 2],
[-2, 2, 2, -2],
[-2, 2, 2, -2]])
>>> np.where(arr>0,2,arr)
array([[ 2. , 2. , -0.03410723, 2. ],
[-2.36938123, 2. , 2. , 2. ],
[-0.15438514, 2. , 2. , -1.70140082],
[-0.2854488 , 2. , 2. , -2.52706882]])

np.where也可以设定更复杂的逻辑关系
如果有两个布尔型数组cond1和cond2,希望根据4种不同的布尔值组合实现不同的赋值操作:
>>> cond1
array([ True, False, True, True, False], dtype=bool)
>>> cond2
array([ True, True, False, False, False], dtype=bool)
>>> result=[]
>>> for i in range(n):
... ····if cond1[i] and cond2[i]:
... ········result.append(0)
... ····elif cond1[i]:
... ········result.append(1)
... ····elif cond2[i]:
... ········result.append(2)
... ····else:
... ········result.append(3)
>> result
[0, 2, 1, 1, 3]
这个表达式可以解释为:
如果两个表达式都为True,则result为0
如果第一个表达式为True,则result为1
如果第二个表达式为True,则result为2
如果两个表达式都不为True,则result为3

这个for循环可以改成简单的np.where表达式如下
>>> np.where(cond1 & cond2, 0, np.where(cond1, 1, np.where(cond2, 2, 3)))
array([0, 2, 1, 1, 3])
cond1 & cond2作为一个判断条件,如果为True则为0,如果为False则执行np.where(cond1)中的表达式,如果为True则为1,如果为False则执行np.where(cond2)中的表达式,如果为True则为2,如果为False则结果为3

当然也可以更加简化,我们可以利用“布尔值在计算过程中可以被当做0或1处理”这个事实,所以还能将其写成下面这样的算术运算:
>>> 1 * (~cond2 & cond1) + 2 * (cond2 & ~cond1) + 3 * ~(cond1 | cond2)
array([0, 2, 1, 1, 3])
这个表达式可以理解为满足cond1的条件,result值为1,满足cond2的条件,result值为2,二者都不满足result值为3,而二者都满足则不复制即为零,True表示满足条件,FALSE表示不满足条件。

数学和统计方法
可通过数组上的一组数学函数对整个数组或某个轴向的数据进行统计计算。sum、mean以及标准差std等聚合计算(aggregation,通常叫做简约(reduction))既可以当值数组的实例方法调用,也可以当做顶级NumPy函数使用:
>>> arr=np.array([[0, 1, 2], [3, 4, 5], [6, 7, 8]])
>>> arr
array([[0, 1, 2],
[3, 4, 5],
[6, 7, 8]])
>>> arr.mean() #计算结果是数组当中所有数值的平均数
4.0
>>> arr.sum() #所有数值的加和
36
mean和sum这类的函数可以接受一个axis参数(用于计算该轴向上的统计值),最终结果是一个少一维的数组:
>>> arr.sum(axis=0) #计算的是纵轴数值总和
array([ 9, 12, 15])
>>> arr.sum(axis=1) #计算的是横轴数值总和
array([ 3, 12, 21])
而cumsum和cumprod之类的方法则不进行聚合,而是产生一个有中间结果组成的数组,表示的是累积的结果。
cumsum表示累加
>>> arr
array([[0, 1, 2],
[3, 4, 5],
[6, 7, 8]])
>>> arr.cumsum()
array([ 0, 1, 3, 6, 10, 15, 21, 28, 36])
>>> arr.cumsum(axis=0) #纵轴累加
array([[ 0, 1, 2],
[ 3, 5, 7],
[ 9, 12, 15]])
>>> arr.cumsum(axis=1) #横轴累加
array([[ 0, 1, 3],
[ 3, 7, 12],
[ 6, 13, 21]])
cumprod表示累积
>>> arr.cumprod()
array([0, 0, 0, 0, 0, 0, 0, 0, 0])
>>> arr.cumprod(axis=1)
array([[ 0, 0, 0],
[ 3, 12, 60],
[ 6, 42, 336]])
>>> arr.cumprod(axis=0)
array([[ 0, 1, 2],
[ 0, 4, 10],
[ 0, 28, 80]])

表4-5:基本数组统计方法
| 方法 | 说明 |
| sum | 对数组中全部或某轴向的元素求和。零长度的数组的sum为0 |
| mean | 算术平均数。零长度的数组的mean为NaN |
| std、var | 分别为标准差和方差,自由度可调(默认为n) |
| min、max | 最大值和最小值 |
| argmin、argmax | 分别为最大和最小元素的索引 |
| cumsum | 所有元素的累计和 |
| cumprod | 所有元素的累计积 |

用于布尔型数组的方法
布尔值会被强制转换为1(True)和0(False)。因此,sum经常被用来对布尔型数组中的True值计数:
>>> arr=randn(100) #随机产生100个值的数组
>>> (arr>0) #根据上述100个随机数,进行判断产生一个True和False的布尔型数组
>>> (arr>0).sum() #统计正直的个数,True为1,False为0
any和all方法,any用于测试数组中是否存在一个或多个True,而all则检查数组中所有值是否是True
>>> bools=np.array([False, False, True, False])
>>> bools.any() #存在一个以上True则显示True
True
>>> bools.all() #存在一个以上False则显示False
False

排序
NumPy数组也可通过sort方法排序
>>> arr=randn(8)
>>> arr
array([ 0.49147829, 0.54156883, -0.38602287, -0.55831323, -0.0087033 , 0.74340158, -1.24390019, -1.02391726])
>>> arr.sort()
>>> arr
array([-1.24390019, -1.02391726, -0.55831323, -0.38602287, -0.0087033 , 0.49147829, 0.54156883, 0.74340158])

>>> arr=randn(9)
>>> arr
array([-0.69778284, 0.30313787, 0.52890605, 0.11275467, 0.32922109, 0.10299694, -0.61234129, -0.59846439, -0.96847564])
sort默认是升序排序
np.sort(array) 返回一个排序后的对象
arr.sort()直接修改原来的数组得到排序后的结果
>>> -np.sort(-arr, kind='quicksort')#实现降序排序,原数组数值替换正负号,进行升序排序后再次替换正负号
array([ 0.52890605, 0.32922109, 0.30313787, 0.11275467, 0.10299694, -0.59846439, -0.61234129, -0.69778284, -0.96847564])

多维数组可以在任何一个轴向上进行排序,需要给sort传递轴编号
>>> arr=np.array([[2, 4, 7], [3, 9, 5], [8, 1, 6]])
>>> arr
array([[2, 4, 7],
[3, 9, 5],
[8, 1, 6]])
>>> arr.sort() #根据横轴进行排序
>>> arr
array([[2, 4, 7],
[3, 5, 9],
[1, 6, 8]])
>>> arr.sort(1) #根据横轴进行排序与arr.sort()结果相同
>>> arr
array([[2, 4, 7],
[3, 5, 9],
[1, 6, 8]])
>>> arr.sort(0) #根据纵轴进行排序
>>> arr
array([[2, 1, 5],
[3, 4, 6],
[8, 9, 7]])
唯一化以及其他的集合逻辑
对于一维数组的集合运算,可用np.unique函数,其能够返回数组中的唯一值并返回已排序的结果
>>> names=np.array(['Bob', 'Joe', 'Will', 'Bob', 'Will', 'Joe', 'Joe'])
>>> np.unique(names)
array(['Bob', 'Joe', 'Will'], dtype='|S4')
函数np.in1d用于测试一个数组中的值在另一个数组中成员资格,返回一个布尔型数组
>>> values=np.array([6, 0, 0, 3, 2, 5, 6])
>>> np.in1d(values, [2, 3, 6])
array([ True, False, False, True, True, False, True], dtype=bool)
表 4-6:数组的集合运算
| 方法 | 说明 |
| unique(x) | 计算x中的唯一元素,并返回有序结果 |
| intersect1d(x, y) | 计算x和y中的公共元素,并返回有序结果 |
| union1d(x, y) | 计算x和y的并集,并返回有序结果 |
| in1d(x, y) | 得到一个表示“x的元素是否包含于y”的布尔型数组 |
| setdiff1d(x, y) | 集合的差,即元素在x中且不在y中 |
| setxor1d(x ,y) | 集合的对称差,即存在于一个数组中但不同时存在于两个数组中的元素 |

原创粉丝点击