Python数据分析工具库-Numpy 数组支持库(二)

1 shape变化及转置

a = np.floor(10*np.random.random((3,4)))

a

array([[ 2., 8., 0., 6.],

[ 4., 5., 1., 1.],

[ 8., 9., 3., 6.]])

a.shape

(3, 4)

a.ravel() # 转化为一维数组

array([ 2., 8., 0., 6., 4., 5., 1., 1., 8., 9., 3., 6.])

a.reshape(6,2) # 将数组a转化为指定shape的数组

array([[ 2., 8.],

[ 0., 6.],

[ 4., 5.],

[ 1., 1.],

[ 8., 9.],

[ 3., 6.]])

a.T # 数组的转置

array([[ 2., 4., 8.],

[ 8., 5., 9.],

[ 0., 1., 3.],

[ 6., 1., 6.]])

a.T.shape

(4, 3)

a.shape

(3, 4)

注意对数组进行reshape操作不会改变原有数组a,但resize会在原有数组a上进行改变:

a.resize((2,6))

a

array([[ 2., 8., 0., 6., 4., 5.],

[ 1., 1., 8., 9., 3., 6.]])

当reshape方法中有参数为-1,则表示numpy会自己计算-1位置的维数,这在很多深度学习模型中可以见到。

a.reshape(3,-1)

array([[ 2., 8., 0., 6.],

[ 4., 5., 1., 1.],

[ 8., 9., 3., 6.]])

2 数组的合并与拆分

concatenate连接

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

y = numpy.array([[7, 8, 9], [10, 11, 12]])

numpy.concatenate([x, y], axis = 0) # 竖直组合

[[ 1 2 3][ 4 5 6][ 7 8 9][10 11 12]]

numpy.concatenate([x, y], axis = 1) # 水平组合

[[ 1 2 3 7 8 9][ 4 5 6 10 11 12]]

横向合并,沿第一个轴进行堆叠,比如:vstack或row_stack

a = np.floor(10*np.random.random((2,2)))

a

array([[ 8., 8.],

[ 0., 0.]])

b = np.floor(10*np.random.random((2,2)))

b

array([[ 1., 8.],

[ 0., 4.]])

np.vstack((a,b))

array([[ 8., 8.],

[ 0., 0.],

[ 1., 8.],

[ 0., 4.]])

纵向合并,沿着第二个轴进行堆叠,比如hstack和column_stack,两者不一样,column_stack在对一维数组进行堆叠时会先将一维数组转化为二维数组,最终返回二维数组。

np.hstack((a,b)) #使用hstack对二维数组进行纵向合并

array([[ 8., 8., 1., 8.],

[ 0., 0., 0., 4.]])

np.column_stack((a,b)) #使用column_stack对二维数组进行纵向合并

array([[ 8., 8., 1., 8.],

[ 0., 0., 0., 4.]])

a = np.array([4.,2.])

b = np.array([3.,8.])

np.column_stack((a,b)) #使用column_stack对一维数组进行纵向合并,返回二维数组

array([[ 4., 3.],

[ 2., 8.]])

np.hstack((a,b)) #使用hstack对一维数组进行纵向合并,返回一维数组

array([ 4., 2., 3., 8.])

array_split ,numpy.array_split(ary, indices_or_sections, axis=0),沿着第一个轴从左至右的顺序切分:

x = np.arange(8.0)

np.array_split(x, 3)

[array([ 0., 1., 2.]), array([ 3., 4., 5.]), array([ 6., 7.])]

x = np.arange(7.0)

np.array_split(x, 3)

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

vsplit,沿着第一个轴切分,相当于split方法中参数axis=0

x = np.arange(16.0).reshape(4, 4)

x

array([[ 0., 1., 2., 3.],

[ 4., 5., 6., 7.],

[ 8., 9., 10., 11.],

[ 12., 13., 14., 15.]])

np.vsplit(x, 2)

[array([[ 0., 1., 2., 3.],

[ 4., 5., 6., 7.]]),

array([[ 8., 9., 10., 11.],

[ 12., 13., 14., 15.]])]

hsplit,沿着第二个轴切分,相当于split方法中参数axis=1

x = np.arange(16.0).reshape(4, 4)

x

array([[ 0., 1., 2., 3.],

[ 4., 5., 6., 7.],

[ 8., 9., 10., 11.],

[ 12., 13., 14., 15.]])

np.hsplit(x, 2)

[array([[ 0., 1.],

[ 4., 5.],

[ 8., 9.],

[ 12., 13.]]),

array([[ 2., 3.],

[ 6., 7.],

[ 10., 11.],

[ 14., 15.]])]

3 数组的复制

完全不复制(No Copy at All)

a = np.arange(12)

b = a # no new object is created

b is a # a and b are two names for the same ndarray object

True

b.shape = 3,4 # changes the shape of a

a.shape

(3, 4)

这种方式的“复制”其实没有实际复制,只是将变量b在内存的索引指向了变量a所在的内存,这样变量a和变量b均指向同一块内存,这时候改变了b就相当于改变了a。

浅复制

使用view方法来创建一个新的数组对象,并把将被复制的数组a的视图(view)复制到新的数组对象c中,这时的c数据完全来自于a,和a保持完全一致,换句话说,c的数据完全由a保管,他们两个的数据变化是一致的:

c = a.view()

c is a

False

c.base is a # c只是a的视图

True

c.flags.owndata

False

c.shape = 2,6 # a的shape不会变化

a.shape

(3, 4)

c[0,4] = 1234 # a的值会相应的变化

a

array([[ 0, 1, 2, 3],

[1234, 5, 6, 7],

[ 8, 9, 10, 11]])

切片也是一种浅复制:

s = a[ : , 1:3] # 将a的第2列与第三列浅复制给s

s[:] = 10 # 将s的所有元素重新赋值为10,也会改变a相应位置的值

a

array([[ 0, 10, 10, 3],

[1234, 10, 10, 7],

[ 8, 10, 10, 11]])

深复制

使用copy方法,不仅将被复制数组的索引复制到新的数组中,也将被复制数组的元素复制到新的数组中。

d = a.copy() # 创建一个新的数组

d is a

False

d.base is a

False

d[0,0] = 9999

a

array([[ 0, 10, 10, 3],

[1234, 10, 10, 7],

[ 8, 10, 10, 11]])

4 Fancy indexing与布尔索引

Fancy indexing是指传递索引数组以便一次得到多个数组元素。使用Fancy indexing时返回数组的shape是索引数组的shape而不是被索引的原数组的shape。

一维数组的Fancy indexing

a = np.arange(12)**2

i = np.array( [ 1,1,3,8,5 ] ) # 索引数组

a[i]

array([ 1, 1, 9, 64, 25])

j = np.array( [ [ 3, 4], [ 9, 7 ] ] )

a[j]

array([[ 9, 16],

[81, 49]])

多维数组的Fancy indexing

a = np.arange(12).reshape(3,4)

a

array([[ 0, 1, 2, 3],

[ 4, 5, 6, 7],

[ 8, 9, 10, 11]])

i = np.array( [ [0,1], # 横向索引

... [1,2] ] )

j = np.array( [ [2,1], # 纵向索引

... [3,3] ] )

a[i,j]

array([[ 2, 5],

[ 7, 11]])

a[i,2]

array([[ 2, 6],

[ 6, 10]])

a[:,j]

array([[[ 2, 1],

[ 3, 3]],

[[ 6, 5],

[ 7, 7]],

[[10, 9],

[11, 11]]])

如果索引数组包含多个相同的索引,那么最后的索引会覆盖前面的索引。

a = np.arange(5)

a[[0,0,2]]=[1,2,3]

a

array([2, 1, 3, 3, 4])

但对于类似“+=”累加的操作却不会叠加两次:

a = np.arange(5)

a[[0,0,2]]+=1

a

array([1, 1, 3, 3, 4])

布尔索引

索引数组元素为布尔类型的值:

a = np.arange(12).reshape(3,4)

b = a 4

b

array([[False, False, False, False],

[False, True, True, True],

[ True, True, True, True]])

a[b]

array([ 5, 6, 7, 8, 9, 10, 11])

a[b] = 0

a

array([[0, 1, 2, 3],

[4, 0, 0, 0],

[0, 0, 0, 0]])

索引数组有多个

a = np.arange(12).reshape(3,4)

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

b2 = np.array([True,False,True,False]) 、

a[b1,:]

array([[ 4, 5, 6, 7],

[ 8, 9, 10, 11]])

a[b1]

array([[ 4, 5, 6, 7],

[ 8, 9, 10, 11]])

a[:,b2]

array([[ 0, 2],

[ 4, 6],

[ 8, 10]])

5 Numpy的线性代数(Linear Algebra)

包含求逆、奇异值分解、生成对角矩阵、解线性方程组Ax=b、计算特征值与特征向量等

import numpy as np

a = np.array([[1.0, 2.0], [3.0, 4.0]])

print(a)

[[ 1. 2.]

[ 3. 4.]]

a.transpose() # 转置

array([[ 1., 3.],

[ 2., 4.]])

np.linalg.inv(a) # 求逆

array([[-2. , 1. ],

[ 1.5, -0.5]])

u = np.eye(2) # 生成对角矩阵

u

array([[ 1., 0.],

[ 0., 1.]])

j = np.array([[0.0, -1.0], [1.0, 0.0]])

np.dot (j, j) # 矩阵乘

array([[-1., 0.],

[ 0., -1.]])

np.trace(u) # 求对角线元素和

2.0

y = np.array([[5.], [7.]])

np.linalg.solve(a, y) # 解线性方程组Ax=b

array([[-3.],

[ 4.]])

np.linalg.eig(j) #计算特征值与特征向量

(array([ 0.+1.j, 0.-1.j]), array([[ 0.70710678+0.j , 0.70710678-0.j ],

[ 0.00000000-0.70710678j, 0.00000000+0.70710678j]]))

相关推荐