numpy

介绍

NumPy(Numerical Python) 是 Python 语言的一个扩展程序库,支持大量的维度数组与矩阵运算,此外也针对数组运算提供大量的数学函数库。

数组对象Ndarray

是一系列 同类型数据 的集合,以 0 下标为开始 进行集合中元素的索引,是用于存放同类型元素的 多维数组

创建数组

创建一个 ndarray 只需调用 NumPy 的 array 函数即可:

numpy.array(object, dtype = None, copy = True, order = None, subok = False, ndmin = 0)

参数说明,object为数组或嵌套数列,dtype为数据类型(可选),copy为对象是否需要复制(可选),order为创建数组的方向(C为行方向,F为列方向,默认为任意方向),ndmin指定生成数组的最小维度
例子代码:

import numpy as np
a=np.array([1,2,3])
b=np.array([[1,2],[3,4]])
c=np.array([1,2,3,4,5],ndmin=2)
d=np.array([1,2,3],dtype=complex)
print(a,"\n\n",b,"\n\n",c,"\n\n",d)

输出结果:

[1 2 3] 

 [[1 2]
 [3 4]] 
 
 [[1 2 3 4 5]] 
 
 [1.+0.j 2.+0.j 3.+0.j]

数组属性

  • NumPy 数组的 维数 称为秩(rank),一维数组的秩为 1,二维数组的秩为 2,以此类推。

  • 在 NumPy中,每一个线性的数组称为是一个轴(axis),也就是 维度(dimensions)。比如说,二维数组相当于是两个一维数组,其中第一个一维数组中每个元素又是一个一维数组。所以一维数组就是 NumPy 中的轴(axis),第一个轴相当于是底层数组,第二个轴是底层数组里的数组。而轴的数量——秩,就是数组的维数。

  • 很多时候可以声明 axis。axis=0,表示沿着第 0 轴进行操作,即对每一列进行操作;axis=1,表示沿着第1轴进行操作,即对每一行进行操作。

  • 注意区分维数与维度的不同

例子代码:

import numpy as np
a=np.arange(24)
print(a,"\n",a.ndim,"\n") #ndarray.ndim返回数组的维数,等于秩
b=a.reshape(2,3,4)   #reshape用来调整数组大小,b为3维了
print(b,"\n",b.ndim,"\n")
c=np.array([[10,4,5],[6,3,8]])
print(c,"\n",c.shape)  #ndarray表示数组的维度,返回一个元组

输出结果:

[ 0  1  2  3  4  5  6  7  8  9 10 11 12 13 14 15 16 17 18 19 20 21 22 23] 
 1
 
[[[ 0  1  2  3]
  [ 4  5  6  7]
  [ 8  9 10 11]]
 [[12 13 14 15]
  [16 17 18 19]
  [20 21 22 23]]] 
 3
 
[[10  4  5]
 [ 6  3  8]] 
 (2, 3)

属性补充:

  • ndarray.size 数组元素的总个数,相当于 .shape 中 n*m 的值
  • ndarray.dtype ndarray 对象的元素类型

创建未初始化或者0-1填充的数组

  • numpy.empty(shape, dtype = float, order = ‘C’),创建未初始化数组
  • numpy.zeros(shape, dtype = float, order = ‘C’),创建以0填充数组
  • numpy.ones(shape, dtype = None, order = ‘C’),创建以1填充数组

参数说明:

参数描述
shape数组形状
dtype数据类型,可选
order‘C’ 用于 C 的行数组,或者 ‘F’ 用于 FORTRAN 的列数组

例子代码:

a=np.empty([3,2],dtype=int)
b=np.empty([3,2],dtype=float)
print(a,"\n\n",b,"\n\n")

c=np.zeros(5) #默认为浮点数
d=np.zeros(5,dtype=int) #dtype可以自定义类型
print(c,"\n\n",d,"\n\n")

e=np.ones(5)#默认为浮点数
f=np.ones([2,4],dtype=int)
print(e,"\n\n",f,"\n\n")

输出结果:

a:[[1 0]
 [2 0]
 [3 0]] 
 
b: [[1. 0.]
 [2. 0.]
 [3. 0.]] 
 
c:[0. 0. 0. 0. 0.] 

 d:[0 0 0 0 0] 
 
e:[1. 1. 1. 1. 1.] 

 f:[[1 1 1 1]
 [1 1 1 1]] 

根据其它数组创建数组

numpy.asarray(a, dtype = None, order = None)

a可以是任意形式的参数,如列表,元组,列表的元组,元组的列表,多维数组
例子代码:

a=[1,2,3]
b=np.asarray(a)
print(a,"\n\n",b,"\n\n")#将列表a转化成为了数组b

c=(1,2,3)
d=np.asarray(c)
print(c,"\n\n",d,"\n\n")#将元组c转化成为了数组d

e=[(1,2,3),(4,5)]
f=np.asarray(e)
print(e,"\n\n",f)

输出结果:

a:[1, 2, 3] 
 b:[1 2 3] 
c:(1, 2, 3) 
 d:[1 2 3] 
e:[(1, 2, 3), (4, 5)] 
 f:[(1, 2, 3) (4, 5)]

从数组范围创建数组

  • numpy.arange(start, stop, step, dtype)
    • step:设定步长
  • np.linspace(start, stop, num=50, endpoint=True, retstep=False, dtype=None)
    • num: 要生成的等步长的样本数量,默认为50,
    • endpoint 该值为 ture 时,数列中中包含stop值,反之不包含,默认是True。
    • retstep 如果为 True 时,生成的数组中会显示间距,反之不显示。

例子代码:

a=np.arange(5)
b=np.arange(5,dtype=float)
c=np.arange(10,20,2)
print(a,b,c)

d=np.linspace(1,10,5)
e=np.linspace(1,10,5,endpoint=False)
f=np.linspace(1,10,5,endpoint=False,retstep=True)
print(d,e,f)

输出结果:

a:[0 1 2 3 4]
b:[0. 1. 2. 3. 4.]
c:[10 12 14 16 18]
d:[ 1.    3.25  5.5   7.75 10.  ] 
e:[1.  2.8 4.6 6.4 8.2] 
f:(array([1. , 2.8, 4.6, 6.4, 8.2]), 1.8)

切片和索引

ndarray对象的内容可以通过索引或切片来访问和修改,与 Python 中 list 的切片操作一样。

  • ndarray 数组可以基于 0 - n 的下标进行索引,切片对象可以通过内置的 slice 函数,并设置 start, stop 及 step 参数进行,从原数组中切割出一个新数组。如下:
  • 通过 冒号 分隔切片参数 start:stop:step 来进行切片操作
    • 冒号 : 的解释:如果只放置一个参数,如 [2],将返回与该索引相对应的单个元素。如果为 [2:],表示从该索引开始以后的所有项都将被提取。如果使用了两个参数,如 [2:7],那么则提取两个索引(不包括停止索引)之间的项。
  • 切片还可以包括 省略号 …

例子代码:

a=np.arange(10)
b=slice(2,6,2) #<class 'slice'>
c=a[b]  #<class 'numpy.ndarray'>
print(a,b,c)

e=np.arange(10)
f=e[2:6:2]
g=e[2:]
print(e,f,g)

h=np.array([[1,2],[4,6,7],[10]])
i=h[1:]
print(h,i)

j=np.array([[23,4,3,6,8,8,5],[23,4,1,5],[3,2,5,1]])
k1=j[...,2]  #每个轴的数据个数不一致时,无效
k2=j[2,...]  #每个轴的数据个数不一致时,无效
l=np.array([[23,4,3,6],[23,4,1,5],[3,2,5,1]])
m1=l[...,2]  #第二列元素
m2=l[2,...]  #第二行元素
n=l[2,1:]
print(k1,k2,m1,m2,n)

o=l[2][1]#或者o=l[2,1],效果一样
print(o)

输出结果:

a:[0 1 2 3 4 5 6 7 8 9]
b:slice(2, 6, 2) 
c:[2 4]

e:[0 1 2 3 4 5 6 7 8 9]
f:[2 4] 
g:[2 3 4 5 6 7 8 9]

h:[list([1, 2]) list([4, 6, 7]) list([10])] 
i:[list([4, 6, 7]) list([10])]

k1:[3, 2, 5, 1] 
k2:[3, 2, 5, 1] 
m1:[3 1 5] 
m2:[3 2 5 1] 
n:[2 5 1]

o:2

高级索引

  • 通过整数数组索引
  • 可以借助切片 : 或 … 与索引数组组合。

例子代码:

a=np.array([[1,2],[4,6]])
b=a[[0,1],[0,1]] #获取数组中(0,0),(1,1)和(2,0)位置处的元素。
print(b)

c = np.array([[0, 1, 2], [3, 4, 5], [6, 7, 8], [9, 10, 11]])
rows = np.array([[0, 0], [3, 3]])
cols = np.array([[0, 2], [0, 2]])
d = c[rows, cols] #获取了 4X3 数组中的四个角的元素。 行索引是 [0,0] 和 [3,3],而列索引是 [0,2] 和 [0,2]
print('这个数组的四个角元素是:')
print(d)

e=np.array([[1,4,6],[2,6,3],[3,4,6]])
"""注意如果每行个数不等时,数组里面数据类型会发生变化,变成了列表),如下:"""
#e=np.array([[1,4,6],[2,6,3],[3,4,6,9]])    type(e):如下:
#array([list([1, 4, 6]), list([2, 6, 3]), list([3, 4, 6, 9])], dtype=object)
f=e[1:10,1:10]
g=e[1:10,[2]]
h=e[1:10,[1,2]]
i=e[...,1:]
print(f,g,h,i)

输出结果:

b:[1 6]

这个数组的四个角元素是:
d:[[ 0  2]
 [ 9 11]]
 
f:[[6 3]
  [4 6]] 
  
 g:[[3]
 	[6]] 
 	
 h:[[6 3]
 	[4 6]] 
 	
 i:[[4 6]
 	[6 3]
 	[4 6]]

广播(Broadcast)

广播(Broadcast)是 numpy 对不同形状(shape)的数组进行数值计算 的方式, 对数组的算术运算通常在相应的元素上进行

  • a.shape=b.shape形状相同时

例子代码:

a=np.array([[12,3,4,5],[3,2,45,5]])
b=np.array([[2,3,4,1],[1,3,5,3]])
print(a*b)  #一一对应相乘
#输出结果如下:
[[ 24   9  16   5]
 [  3   6 225  15]]
  • 形状不同时,自动触发广播机制

例子代码:

a = np.array([[ 0, 0, 0],
          [10,10,10],
          [20,20,20],
          [30,30,30]])
b = np.array([1,2,3])
print(a + b)
#输出结果如下:
[[ 1  2  3]
[11 12 13]
[21 22 23]
[31 32 33]]
  • 如何通过广播与数组兼容?如下:

例子代码:

a = np.array([[ 0, 0, 0],
           [10,10,10],
           [20,20,20],
           [30,30,30]])
b = np.array([1,2,3])
b_broadcast=np.tile(b,(4,1))
print(b_broadcast)
print(a + b_broadcast)

"""np.tile()介绍"""
#就是将原矩阵横向、纵向地复制。tile 是瓷砖的意思,顾名思义,这个函数就是把数组像瓷砖一样铺展开来。
c=np.tile(b,[3,4]) #用(3,4)也行
print(c)

输出结果:

[[1 2 3]
 [1 2 3]
 [1 2 3]
 [1 2 3]]
 
[[ 1  2  3]
 [11 12 13]
 [21 22 23]
 [31 32 33]]
 
[[1 2 3 1 2 3 1 2 3 1 2 3]
 [1 2 3 1 2 3 1 2 3 1 2 3]
 [1 2 3 1 2 3 1 2 3 1 2 3]]

迭代数组

NumPy 迭代器对象 numpy.nditer 提供了一种灵活访问一个或者多个数组元素的方式。

遍历数组-例子代码:

a=np.arange(6).reshape(2,3)
"""[[0 1 2]
 	[3 4 5]]"""
for b in np.nditer(a):
    print(b,end=",")
# 输出结果为:0,1,2,3,4,5,
for b in np.nditer(a.T):
    print(b,end=",")
# 输出结果为:0,1,2,3,4,5,
"""可以看出a 和 a.T 的遍历顺序是一样的,也就是他们在内存中的存储顺序也是一样的
	且遍历顺序默认是行序优先(row-major order,或者说是 C-order)
"""


x=a.T.copy(order='C')
"""[[0 3]
 	[1 4]
 	[2 5]]"""
for b in np.nditer(x):
    print(b,end=",")
# 输出结果为:0,3,1,4,2,5,
"""a.T.copy(order='C')的存储方式跟上面两者不一样了,导致结果不一样"""


""" 可以通过显式设置,来强制 nditer 对象使用某种顺序:"""
for c in np.nditer(x,order='F'):
    print(c,end=",")
#输出结果为:0,1,2,3,4,5,

修改数组-例子代码:

a=np.arange(5)
for x in np.nditer(a,op_flags=['readwrite']):
    x[...]=x*2
print(a)
#输出结果为[0 2 4 6 8]

可以使用 numpy.ndarray.flat 数组迭代器来进行迭代

例子代码:

a=np.arange(6).reshape(3,2)
for x in a.flat:
    print(x,end=",")
#输出结果为:0,1,2,3,4,5,

"""如果不是用迭代器,效果如下"""
for x in a:
    print(x)
 """[0 1]
	[2 3]
	[4 5]"""

数组操作

数组展开

  • 语法:ndarray.flatten(order=‘C’),修改不影响原数组
  • 语法:numpy.ravel(a, order=‘C’),修改会影响原数组
a=np.arange(9).reshape(3,3)

b=a.flatten()
print(b)  # [0 1 2 3 4 5 6 7 8]
b[1]=10
print(a)
"""[[0 1 2]
 	[3 4 5]
 	[6 7 8]]"""
 	
c=a.ravel()
print(c) #[0 1 2 3 4 5 6 7 8]
c[1]=10
print(a)
"""[[ 0 10  2]
 	[ 3  4  5]
 	[ 6  7  8]]"""

轴交换(维度交换)

  • numpy.rollaxis(arr, axis, start),向后滚动特定的轴到一个特定位置
    • arr:数组
    • axis:要向后滚动的轴,其它轴的相对位置不会改变
    • start:默认为零,表示完整的滚动。会滚动到特定位置。
  • numpy.swapaxes(arr, axis1, axis2),用于交换数组的两个轴
    • arr:输入的数组
    • axis1:对应第一个轴的整数
    • axis2:对应第二个轴的整数

例子代码:

a=np.array([[[12,23],[20,4]],[[82,9],[2,54]]])
b=np.rollaxis(a,2) #将2轴滚动到0轴后面
"""[[[12 20]
  	[82  2]]
 	[[23  4]
  	[ 9 54]]"""
c=np.rollaxis(a,2,1)  # 将2轴滚动到1轴后面
"""[[[12 20]
  	[23  4]]
 	[[82  2]
  	[ 9 54]]]""" 
d=np.swapaxes(a,2,0)  #交换2轴和0轴
 """[[[12 82]
  	[20  2]]
 	[[23  9]
  	[ 4 54]]]"""
print(b,"\n\n",c,"\n\n",d)

针对b=np.rollaxis(a,2)输出结果,进行分析:

12(000)->(000)1223(001)->(010)20
20(010)->(100)824(011)->(110)2
82(100)->(001)239(101)->(011)4
2(110)->(101)954(111)->(111)54

注:上表类似(100)这样的,第一个数字代表2轴,第二个数字代表1轴,第三个数字代表0轴,其它的轴顺序改变是同样的道理,类比即可。

连接数组

  • numpy.concatenate((a1, a2, …), axis) 用于沿指定轴连接相同形状的两个或多个数组
  • numpy.stack(arrays, axis),用于沿新轴连接数组序列
  • hstack 水平堆叠序列中的数组(列方向)
  • vstack 竖直堆叠序列中的数组(行方向)

例子代码:

a1 = np.array([[1, 2], [3, 4]])
a2 = np.array([[5, 6], [7, 8]])
b = np.concatenate((a1, a2), axis=0)  # 使用下面的[]号也行
c = np.concatenate([a1, a2], axis=1)
print(b, "\n\n", c)
d = np.stack((a1, a2), axis=0)
e = np.stack((a1, a2), axis=1)
print(d, "\n\n", e)
f = np.hstack((a1, a2))
g = np.vstack((a1, a2))
print(f, "\n\n", g)

输出结果:

b:[[1 2]
   [3 4]
   [5 6]
   [7 8]] 
 
c:[[1 2 5 6]
   [3 4 7 8]]
 
d:[[[1 2] #特别留意d和a,e和c的不同,叠加的可有三层括号"[]",连接与叠加是不同的
  	[3 4]]
 
 	[[5 6]
 	 [7 8]]] 
  
e: [[[1 2]
  	[5 6]]
  	
 	[[3 4]
 	 [7 8]]]
  
 f:[[1 2 5 6]
 	[3 4 7 8]] 
 
 g:[[1 2]
 	[3 4]
 	[5 6]
 	[7 8]]

np.concatenate((a1, a2), axis=0)结果分析:

1(0 0)2(0 1)
3 (1 0)4(1 1)
5 (0 0)6(0 1)
7 (1 0)8(1 1)
0轴都是0的串起来0轴都是1的串起来

np.concatenate([a1, a2], axis=1)结果分析:

1(0 0 )2(0 1)5 (0 0)6(0 1)1轴都是0的串起来
3 (1 0)4(1 1 1)7 (1 0)8(1 1)1轴都是1的串起来

分割数组

  • numpy.split(ary, indices_or_sections, axis),沿特定的轴将数组分割为子数组
  • numpy.hsplit,用于水平分割数组,通过指定要返回的相同形状的数组数量来拆分原数组。
  • numpy.vsplit ,沿着垂直轴分割,其分割方式与hsplit用法相同。

例子代码:

a = np.array([1, 2, 3, 4, 5, 65, 6, 9, 34])
b = np.split(a, 3)  # a必需要能够平均分为3份
#[array([1, 2, 3]), array([ 4,  5, 65]), array([ 6,  9, 34])] 
c = np.split(a, [4, 7])  # 在一维数组中表明的位置分割
#[array([1, 2, 3, 4]), array([ 5, 65,  6]), array([ 9, 34])]
print(b, "\n\n", c)


d = np.array([[1, 2, 4, 5, 6, 2, 6, 4, 2], [2, 3, 5, 6, 7, 4, 3, 2, 8]])
e = np.hsplit(d, 3)
"""
[array([[1, 2, 4],
       [2, 3, 5]]), array([[5, 6, 2],
       [6, 7, 4]]), array([[6, 4, 2],
       [3, 2, 8]])] """
f = np.floor(10 * np.random.random((2, 6)))
""" [[5. 0. 3. 1. 0. 5.]
	 [3. 0. 9. 3. 5. 1.]] """
g = np.vsplit(f, 2)
#[array([[5., 0., 3., 1., 0., 5.]]), array([[3., 0., 9., 3., 5., 1.]])]
print(e,"\n\n",f, "\n\n",g)

数组元素添加与删除

  • numpy.resize(arr, shape)返回指定大小的新数组。如果新数组大小大于原始大小,则包含原始数组中的元素的副本。
  • numpy.append(arr, values, axis=None) ,在数组的末尾添加值。 追加操作会分配整个数组,并把原来的数组复制到新数组中。 此外,*输入数组的维度必须匹配否则将生成ValueError。append 函数返回的始终是一个一维数组。
  • numpy.insert(arr, obj, values, axis) ,在给定索引之前,沿给定轴在输入数组中插入值。如果值的类型转换为要插入,则它与输入数组不同。 插入没有原地的,函数会返回一个新数组。 此外,如果未提供轴,则输入数组会被展开。
  • Numpy.delete(arr, obj, axis) 返回从输入数组中删除指定子数组的新数组。 与 insert() 函数的情况一样,如果未提供轴参数,则输入数组将展开。
  • numpy.unique(arr, return_index, return_inverse, return_counts),用于去除数组中的重复元素。

例子代码:

a=np.array([[1,2,3],[4,5,6]])
b=np.resize(a,(3,2))#
c=np.resize(a,(3,3))#数组中元素不够了,会从第一行开始再继续选,因此会有重复值
d=np.resize(a,(3,1)) #选够3个元素来组成维度为(3,1)的数组,多余的弃掉
print(b,"\n\n",c,"\n\n",d)
"""
[[1 2]
 [3 4]
 [5 6]]
  
 [[1 2 3]
 [4 5 6]
 [1 2 3]] 
 
 [[1]
 [2]
 [3]]
"""


e=np.append(a,[7,8,9])
f=np.append(a,[[7,8,9]],axis=0) #沿0轴添加元素
g=np.append(a,[[7,8,9],[10,11,12]],axis=1)  #沿1轴添加元素
print(e,"\n\n",f,"\n\n",g)
"""
[1 2 3 4 5 6 7 8 9] 

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


h=np.array([[1,2,],[3,4,],[5,6]])
i=np.insert(h,3,[7,8]) #未传递 Axis 参数。 在插入之前输入数组会被展开。
#传递了 Axis 参数。 会广播值数组来配输入数组。如下:
j=np.insert(h,1,[13],axis=0) #沿0轴广播
k=np.insert(h,1,[13],axis=1) #沿1轴广播
print(i,"\n\n",j,"\n\n",k)
"""
[1 2 3 7 8 4 5 6] 

 [[ 1  2]
 [13 13]
 [ 3  4]
 [ 5  6]] 
 
 [[ 1 13  2]
 [ 3 13  4]
 [ 5 13  6]]
"""



l=np.arange(12).reshape(3,4)
m=np.delete(l,5) #未传递 Axis 参数。 在插入之前输入数组会被展开。
n=np.delete(l,1,axis=1)  #删除第二列
"""
[ 0  1  2  3  4  6  7  8  9 10 11] 

 [[ 0  2  3]
 [ 4  6  7]
 [ 8 10 11]]
"""


o=np.array([1,2,4,5,3,2,4,52,2,2])
p=np.unique(o)
q=np.unique(o,return_index=True)  #新在旧的位置
r=np.unique(o,return_inverse=True)  #旧在新的位置
s=np.unique(o,return_counts=True)   #出现次数
print(q,"\n\n",r,"\n\n",s)
"""
(array([ 1,  2,  3,  4,  5, 52]), array([0, 1, 4, 2, 3, 7], dtype=int64)) 
 (array([ 1,  2,  3,  4,  5, 52]), array([0, 1, 3, 4, 2, 1, 3, 5, 1, 1], dtype=int64)) 
 (array([ 1,  2,  3,  4,  5, 52]), array([1, 4, 1, 2, 1, 1], dtype=int64))
 """

菜鸟教程:https://www.runoob.com/numpy/numpy-tutorial.html

  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值