python:numpy数组运算、排序、统计、随机数生成

版权声明:本文为博主原创文章,未经博主允许不得转载。 https://blog.csdn.net/LY_ysys629/article/details/73694453

主要内容

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

2) 将条件逻辑表述为数组运算

3) 数学与统计方法

4) 用于布尔型数组的方法

5) 排序

6) 唯一化以及其他的集合逻辑

7) 用于数组的文件输入输出

8) 线性代数

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

import numpy as np
points = np.arange(-5,5,1)

print points
xs,ys  = np.meshgrid(points,points)

ys
[-5 -4 -3 -2 -1  0  1  2  3  4]

array([[-5, -5, -5, -5, -5, -5, -5, -5, -5, -5],
       [-4, -4, -4, -4, -4, -4, -4, -4, -4, -4],
       [-3, -3, -3, -3, -3, -3, -3, -3, -3, -3],
       [-2, -2, -2, -2, -2, -2, -2, -2, -2, -2],
       [-1, -1, -1, -1, -1, -1, -1, -1, -1, -1],
       [ 0,  0,  0,  0,  0,  0,  0,  0,  0,  0],
       [ 1,  1,  1,  1,  1,  1,  1,  1,  1,  1],
       [ 2,  2,  2,  2,  2,  2,  2,  2,  2,  2],
       [ 3,  3,  3,  3,  3,  3,  3,  3,  3,  3],
       [ 4,  4,  4,  4,  4,  4,  4,  4,  4,  4]])
xs
array([[-5, -4, -3, -2, -1,  0,  1,  2,  3,  4],
       [-5, -4, -3, -2, -1,  0,  1,  2,  3,  4],
       [-5, -4, -3, -2, -1,  0,  1,  2,  3,  4],
       [-5, -4, -3, -2, -1,  0,  1,  2,  3,  4],
       [-5, -4, -3, -2, -1,  0,  1,  2,  3,  4],
       [-5, -4, -3, -2, -1,  0,  1,  2,  3,  4],
       [-5, -4, -3, -2, -1,  0,  1,  2,  3,  4],
       [-5, -4, -3, -2, -1,  0,  1,  2,  3,  4],
       [-5, -4, -3, -2, -1,  0,  1,  2,  3,  4],
       [-5, -4, -3, -2, -1,  0,  1,  2,  3,  4]])

2) 将条件逻辑表述维数组运算

np.where()函数是三元表达式:x if condition else y 的矢量化版本,假设,我们有一个布尔数组和两个数组

xarr = np.array([1,2,3,4,5])

yarr = np.array([6,7,8,9,10])

cond = np.array([True,False,True,True,False,])

加入我们想根据cond数组的情况来选取xarr或yarr数组中的值,有两种方法,一种是列表推导式,另外一种是矢量化

##列表推导式
%timeit  result = [(x if c else y) for x,y,c in zip(xarr,yarr,cond)]
The slowest run took 14.83 times longer than the fastest. This could mean that an intermediate result is being cached.
1000000 loops, best of 3: 1.77 µs per loop
result
[1, 7, 3, 4, 10]
##  矢量化
%timeit result = np.where(cond,xarr,yarr)
The slowest run took 13.14 times longer than the fastest. This could mean that an intermediate result is being cached.
1000000 loops, best of 3: 827 ns per loop
result
array([ 1,  7,  3,  4, 10])

从上述结果真可以看出,矢量化的计算速度大概是列表计算的三倍,注意返回结果类型的不一致!np.where函数的参数还可以是标量

arr = np.random.randn(4,4)
arr
array([[ 0.81362115, -0.59091357,  0.04834518,  0.31279457],
       [ 0.14034937, -0.495634  , -1.65939013, -0.06717819],
       [ 1.27779012,  1.00333966, -1.89590419,  0.06417592],
       [-0.39706132, -0.55924097,  0.19493047, -2.09199616]])
np.where(arr>0,2,-2)
array([[ 2, -2,  2,  2],
       [ 2, -2, -2, -2],
       [ 2,  2, -2,  2],
       [-2, -2,  2, -2]])
arr
array([[ 0.81362115, -0.59091357,  0.04834518,  0.31279457],
       [ 0.14034937, -0.495634  , -1.65939013, -0.06717819],
       [ 1.27779012,  1.00333966, -1.89590419,  0.06417592],
       [-0.39706132, -0.55924097,  0.19493047, -2.09199616]])

注意,条件逻辑表达式不改变原数组

np.where(arr>0,2,arr)#只在条件为真是做出改变
array([[-1.05581125, -0.33226037,  2.        , -0.35399731],
       [ 2.        , -0.85778503,  2.        , -0.63576095],
       [ 2.        ,  2.        , -0.76836718,  2.        ],
       [-0.04934349, -0.95880935,  2.        , -1.00340544]])

还可以嵌套

cond1 = np.array([True,False,True,True,True,])

np.where(cond & cond1,0,np.where(cond1,1,2))
array([0, 2, 0, 0, 1])

另外,布尔型数据还可以在计算过程中被当做0或1处理

result = 1*(cond - cond1) + 2*(cond+cond1)
C:\Program Files\anaconda\lib\site-packages\ipykernel\__main__.py:1: DeprecationWarning: numpy boolean subtract, the `-` operator, is deprecated, use the bitwise_xor, the `^` operator, or the logical_xor function instead.
  if __name__ == '__main__':
result
array([2, 0, 2, 2, 3])

3)数学和统计方法

比如sum、mean、std等聚合计算(aggregation,通常叫做约减(reduction)),既可以当做数组的实例方法调用(array.sum()),还可以当做顶级Numpy函数使用sum(array)。

arr = np.ones((4,5))
arr
array([[ 1.,  1.,  1.,  1.,  1.],
       [ 1.,  1.,  1.,  1.,  1.],
       [ 1.,  1.,  1.,  1.,  1.],
       [ 1.,  1.,  1.,  1.,  1.]])
arr.mean()
1.0
np.mean(arr)
1.0
arr.sum()
20.0
arr
array([[ 1.,  1.,  1.,  1.,  1.],
       [ 1.,  1.,  1.,  1.,  1.],
       [ 1.,  1.,  1.,  1.,  1.],
       [ 1.,  1.,  1.,  1.,  1.]])

注意,聚合函数不改变原数组

np.sum(arr)
20.0
arr[:,2] = 2
arr
array([[ 1.,  1.,  2.,  1.,  1.],
       [ 1.,  1.,  2.,  1.,  1.],
       [ 1.,  1.,  2.,  1.,  1.],
       [ 1.,  1.,  2.,  1.,  1.]])
arr.sum(0)#纵轴方向\
13
arr
array([0, 1, 3, 4, 5])
arr.sum(1)#横轴方向
array([ 6.,  6.,  6.,  6.])
arr.cumsum(0)#纵轴方向的累计和,放回新数组
array([[ 1.,  1.,  1.,  1.,  1.],
       [ 2.,  2.,  2.,  2.,  2.],
       [ 3.,  3.,  3.,  3.,  3.],
       [ 4.,  4.,  4.,  4.,  4.]])

基本数组统计方法

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

4) 用于布尔型数组的方法

1) sum 统计布尔型数组中True的个数,由于布尔型数组中True会被当成1来参加运算。

2) any 用于测试数组中是否存在一个或多个True

3) all 用来检查数组中所有值是否都是True

4) 另外 any、all也可以用与非布尔型数组,所有非0元素会被当做True

import numpy as np

bools = np.array([False,False,True,False,True])

bools.sum()
2
bools.any()
True
bools.all()
False

从上述结果中,any和all说明bools中有True但不全是,而sum统计了True的个数。

5)排序

arr = np.arange(5)

arr[2]=5
arr
array([0, 1, 5, 3, 4])
arr.sort()
arr
array([0, 1, 3, 4, 5])
np.sort(arr)
array([0, 1, 3, 4, 5])
array = np.arange(1,5,0.5).reshape(2,4)
array
array([[ 1. ,  1.5,  2. ,  2.5],
       [ 3. ,  3.5,  4. ,  4.5]])
array[:,1] = np.array([3.5,1.5]).T
array
array([[ 1. ,  3.5,  2. ,  2.5],
       [ 3. ,  1.5,  4. ,  4.5]])
array.sort(0)#在纵轴上排序
array
array([[ 1. ,  1.5,  2. ,  2.5],
       [ 3. ,  3.5,  4. ,  4.5]])
array[:,1] = np.array([3.5,1.5]).T
print array
array.sort(1)#在横轴上排序
array
[[ 1.   3.5  2.   2.5]
 [ 3.   1.5  4.   4.5]]


array([[ 1. ,  2. ,  2.5,  3.5],
       [ 1.5,  3. ,  4. ,  4.5]])

python内置排序程序

array = np.array([1,2,6,3,5,4])

array
array([1, 2, 6, 3, 5, 4])
sorted(array)#python内置一般返回列表
[1, 2, 3, 4, 5, 6]
array#内置不改变原来是数组?
array([1, 2, 6, 3, 5, 4])

注意,sort会在原数组上做修改

6) 唯一化以及其他的集合逻辑

numpy提供一些针对**一维**ndarray的基本集合运算,最常用的是np.unique(),它用于找出数组中的唯一值并返回已排序的结果

names = np.array(['a','b','c','a','c'])
names
array(['a', 'b', 'c', 'a', 'c'], 
      dtype='|S1')
np.unique(names)
array(['a', 'b', 'c'], 
      dtype='|S1')
names
array(['a', 'b', 'c', 'a', 'c'], 
      dtype='|S1')
ints = np.array([3,3,3,2,2,2,1,1,4,4])
ints
array([3, 3, 3, 2, 2, 2, 1, 1, 4, 4])
%timeit 
The slowest run took 42.94 times longer than the fastest. This could mean that an intermediate result is being cached.
100000 loops, best of 3: 3.8 µs per loop
np.unique(ints)
array([1, 2, 3, 4])
#上述代码实现功能可以python来实现
%timeit sorted(set(ints))
The slowest run took 25.40 times longer than the fastest. This could mean that an intermediate result is being cached.
1000000 loops, best of 3: 1.75 µs per loop
sorted(set(ints))
[1, 2, 3, 4]

可以看出并不是所有的内置都是效率低的~

np.in1d用于测试一个数组中的值是否存在于另外一个数组中,并返回一个大小和测试数组一样的布尔型数组

value = np.array([6,0,0,3,2,5])
np.in1d(value,[2,3,6])
array([ True, False, False,  True,  True, False], dtype=bool)

常见的数组集合运算

方法 说明
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) 集合的对称差(异或),即存在于一个数组中但不同时存在于两个数组中的元素

7) 用于数组的文件输入输出

numpy能够读写磁盘上的文本数据和二进制数据,pandas中有将表格型数据读取到内存的工具

将数组以二进制格式保存到磁盘

np.save和np.load是读写磁盘数据的两个主要函数,默认情况下,数组是以未压缩的原始二进制格式保存在扩展名为.npy的文件中。

arr = np.arange(10)
arr
array([0, 1, 2, 3, 4, 5, 6, 7, 8, 9])
np.save('E:\python\juputer\sameArray',arr)#可以不加后缀,系统会自动加.npy
np.load('E:\python\juputer\sameArray.npy')#必须有后缀
array([0, 1, 2, 3, 4, 5, 6, 7, 8, 9])

此外,还可以将多个数组保存到一个压缩文件中,将数组以关键字参数的形式传入即可

array = np.array([1,2,0,0,0,0,0])

np.savez('bb',a=arr,b=array)#貌似只能压缩到默认路径下,不知道什么原因
arch = np.load('bb.npz')
arch['b']
array([1, 2, 0, 0, 0, 0, 0])

存取文本数据

从文本中加载说句是一个非常标准的任务。numpy主要有np.loadtxt()和np.genfromtxt()函数,pandas主要有read_csv和read_table()函数。

arr = np.random.randn(4,3)
arr
array([[-0.51108593,  0.72750055, -0.15797328],
       [-0.36643894,  0.55478468,  0.30060344],
       [-0.76537983, -0.28501039, -0.14497014],
       [ 0.72564297, -1.27952004,  0.30936996]])
np.savetxt('test.txt',arr)
arr = np.loadtxt('test.txt')
arr
array([[-0.51108593,  0.72750055, -0.15797328],
       [-0.36643894,  0.55478468,  0.30060344],
       [-0.76537983, -0.28501039, -0.14497014],
       [ 0.72564297, -1.27952004,  0.30936996]])

8)线性代数

线性代数(如矩阵乘法、矩阵分解、行列式以及其他方阵等)是任何数组库的重要组成部分。numpy提供了一个用于矩阵乘法的dot函数(数组方法),实现数组的点积。

常用的numpy.linalg函数

函数 说明
diag 以一维数组的形式放回方阵的对角线(或非对角线元素),或将一维数组换为方阵(非对角线元素为0)
dot 矩阵乘法
trace 计算对角线元素和
det 计算矩阵的行列式
eig 计算方阵的特征值和特征向量
inv 计算方阵的逆
pinv 计算矩阵的Moore-Penrose伪逆
qr 计算qr分解
svd 计算奇异值(SVD)
solve 解线性方程组Ax=b,其中A为一个方阵
lstsq 计算Ax=b的最小二乘解
x = np.arange(1,12,2).reshape(2,3)
x
array([[ 1,  3,  5],
       [ 7,  9, 11]])
y = np.arange(2,13,2).reshape(3,2)
y
array([[ 2,  4],
       [ 6,  8],
       [10, 12]])
np.dot(x,y)#等价于x.dot(y)
array([[ 70,  88],
       [178, 232]])
y
array([[ 2,  4],
       [ 6,  8],
       [10, 12]])
x = np.random.randn(5,5)
x
array([[ 1.63103816,  0.71983566,  1.10352515, -0.27938298,  0.11040744],
       [ 0.41088167, -0.73636959,  1.39466507,  0.02659672, -1.20904744],
       [ 0.5186612 , -1.86480014,  2.89604141, -0.63832998, -0.49133989],
       [ 1.63042984,  0.57143769, -1.11857589, -0.02013889,  0.46964764],
       [ 1.23888832,  3.42855521, -2.36622283, -1.22878746,  1.80597763]])
mat = x.T.dot(x)
np.linalg.inv(mat)
array([[ 0.27742733, -0.19565147, -0.16151662,  0.02161428, -0.04933913],
       [-0.19565147,  0.67591051,  0.47450978,  0.64285176, -0.03838762],
       [-0.16151662,  0.47450978,  0.6679418 ,  1.00350966,  0.69607497],
       [ 0.02161428,  0.64285176,  1.00350966,  2.60588578,  1.45256531],
       [-0.04933913, -0.03838762,  0.69607497,  1.45256531,  1.87265356]])
mat.T.dot(np.linalg.inv(mat))
array([[  1.00000000e+00,   1.10290647e-16,   6.50206020e-17,
         -9.56263991e-18,   2.31165248e-16],
       [  1.86021783e-16,   1.00000000e+00,  -4.42906701e-16,
         -2.93319024e-16,  -1.88919268e-15],
       [  4.43545563e-17,   1.16736094e-15,   1.00000000e+00,
          8.64035632e-16,   4.01786135e-16],
       [ -9.10610531e-17,   2.30215482e-16,   2.61428391e-16,
          1.00000000e+00,  -9.26009142e-17],
       [  2.00085966e-16,  -1.58177563e-15,  -1.19547067e-15,
         -1.29203693e-15,   1.00000000e+00]])
s,v,d = np.linalg.svd(mat)
s
array([[-0.16523474,  0.77808826,  0.58918158,  0.13972992, -0.02483462],
       [-0.64883151,  0.20661516, -0.29383095, -0.64803915,  0.17331036],
       [ 0.64914815,  0.49923165, -0.41237116, -0.21362089,  0.33718034],
       [ 0.10505073, -0.30923038,  0.52695933, -0.24319507,  0.74599661],
       [-0.3453783 ,  0.08386396, -0.34466264,  0.67508746,  0.54694172]])
v
array([ 37.27592672,   9.26487289,   1.86483196,   0.86523652,   0.23402418])
d
array([[-0.16523474, -0.64883151,  0.64914815,  0.10505073, -0.3453783 ],
       [ 0.77808826,  0.20661516,  0.49923165, -0.30923038,  0.08386396],
       [ 0.58918158, -0.29383095, -0.41237116,  0.52695933, -0.34466264],
       [ 0.13972992, -0.64803915, -0.21362089, -0.24319507,  0.67508746],
       [-0.02483462,  0.17331036,  0.33718034,  0.74599661,  0.54694172]])

9)随机数生成

numpy.random模块是对python内置random进行补充,增加了一些用于高效生成多种概率分布的样本值的函数,例如,你可以用normal来得到一个标准正态分布的4*4样本数组。

常用的随机数生成函数

函数 说明
seed 确定随机数生成器的种子
permutation 返回一个序列的随机排列或返回一个随机排列的范围
shuffle 对一个序列就地随机排列
rand 产生均匀分布的样本值
randint 从给定的上下限范围内随机选取整数
randn 产生正态分布(平均数为0,标准差为1)的样本值,类似于MATLAB接口
binomial 产生二项分布的样本值
normal 产生正态分布(高斯分布)的样本值
beta 产生beta分布的样本值
chisquare 产生卡方分布的样本值
gamma 产生gamma分布的样本值
uniform 产生[0,1)均匀分布的样本值
#产生高斯分布
sample = np.random.normal(size=(4,4))
sample
array([[ 0.89509853, -0.83225074,  1.29474565,  0.45655647],
       [-1.43400126,  1.32985572,  2.30055355,  2.46808663],
       [-2.4563378 , -0.66266506, -1.15600003, -0.60034993],
       [-1.79678809, -0.69896066,  1.02434411,  0.1271823 ]])

总结

1)条件逻辑表达式不改变原数组,会返回新的布尔型数组

2)聚合函数不改变原数组,返回结果值

3)监测和检验函数不改变原数组,返回布尔型数据

4)排序函数能够改变原数组,在原来的数据上修改

5)唯一化及集合逻辑不改变原数组,返回新的数组

6)线性代数、矩阵运算不改变原数组,返回结果数组

7)切片相当于引用,指向同一内存区,因此不管改变原数组,还是新的引用变量都会改变原数组

8) numpy元素级通用函数不改变原数组

猜你喜欢

转载自blog.csdn.net/LY_ysys629/article/details/73694453