主要内容
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元素级通用函数不改变原数组