



NumPy(Numerical Python)是Python语言的一个扩展程序库,支持大量的维度数组与矩阵运算,此外,也针对数组运算提供大量的数学函数库。NumPy对于scikit-learn来说是至关重要的,因为scikit-learn使用NumPy数组形式的数据来进行处理,所以需要把数据都转换成NumPy数组的形式,而多维数组也是NumPy的核心功能之一。
NumPy是一个运行速度非常快的数学库,主要用于数组计算,包含:
(1)一个强大的N维数组对象ndarray。
(2)广播功能函数。
(3)整合C/C++/FORTRAN代码的工具。
(4)线性代数、傅里叶变换、随机数生成等功能。
NumPy数组是一个多维数组,称为ndarray。NumPy的创建方法有以下三种,分别为:用特殊函数创建、从已有的数组创建数组以及从数值范围创建数组。
注意: 在ndarray结构中,里面的元素必须是同一类型的,如果不是,会自动地向下进行。
【例2-1】 创建数组和数列。
import numpy as np
#numpy和列表的形式区别(有无逗号)
ar=np.array([1,2,3,4,5])
list1=[1,2,3,4,5]
print(ar,type(ar)) #输出结果中没有逗号分隔
print(list1,type(list1)) #输出结果中有逗号分隔
运行程序,输出如下。
[1 2 3 4 5]<class 'numpy.ndarray'>
[1, 2, 3, 4, 5]<class 'list'>
ndarray数组除了可以使用底层ndarray构造器来创建外,也可以通过以下几种方式来创建。
1)numpy.zeros()方法
numpy.zeros()方法用于创建指定大小的数组,数组元素以0来填充,方法的格式为:
numpy.zeros(shape,dtype=float,order= 'C')
其中,shape为数组形状;dtype为数据类型,可选;order取'C'时用于C的行数组,取'F'时用于FORTRAN的列数组。
【例2-2】 利用numpy.zeros()方法创建指定大小的0数组。
import numpy as np
#默认为浮点数
x=np.zeros(6)
print(x)
#设置类型为整数
y=np.zeros((6,),dtype=int)
print(y)
#自定义类型
z=np.zeros((2,2),dtype=[('x','i4'),('y','i4')])
print(z)
运行程序,输出如下。
[0.0.0.0.0.0.]
[0 0 0 0 0 0]
[[(0,0)(0,0)]
[(0,0)(0,0)]]
2)numpy.empty()方法
numpy.empty()方法用来创建一个指定形状(shape)、数据类型(dtype)且未初始化的数组。方法的格式为:
numpy.empty(shape,dtype=float,order= 'C')
其中,shape为数组形状;dtype为数据类型,可选;order有'C'和'F'两个选项,分别代表行优先和列优先。
【例2-3】 利用numpy.empty()方法创建一个空数组。
import numpy as np
x=np.empty([3,2],dtype= int)
print(x)
运行程序,输出如下。
[[857761391 543236140]
[1701868915 1952804466]
[1953068832 174137448]]
3)numpy.ones()方法
numpy.ones()方法用于创建指定形状的数组,数组元素以1来填充,方法的格式为:
numpy.ones(shape,dtype=None,order= 'C')
其中,shape为数组形状;dtype为数据类型,可选;order取'C'时用于C的行数组,取'F'时用于FORTRAN的列数组。
【例2-4】 利用numpy.ones()方法创建一个全1数组。
import numpy as np
#默认为浮点数
x=np.ones(5)
print(x)
#自定义类型
x=np.ones([2,2],dtype= int)
print(x)
运行程序,输出如下。
[1.1.1.1.1.]
[[1 1]
[1 1]]
4)numpy.full()方法
numpy.full()方法用于创建指定形状的数组,数组元素以fill_value来填充,方法的格式为:
numpy.full(shape,fill_value,dtype=None,order='C')
其中,shape为新数组的形状大小;fill_value将被赋值给新数组的元素值;dtype为指定数组元素的数据类型;order有'C'和'F'两个选项,分别代表行优先和列优先。
【例2-5】 创建一个填充给定值的数组。
import numpy as np
np.full([2,3],3,dtype=int)
运行程序,输出如下。
array([[3,3,3],
[3,3,3]])
除了可以利用函数创建特殊数组外,NumPy还提供了相关函数用于实现从已有的数组创建数组,下面对各函数进行介绍。
1)numpy.asarray()函数
numpy.asarray()类似numpy.array(),但numpy.asarray()的参数只有三个,比numpy.array()少两个。numpy.asarray()函数的格式为:
numpy.asarray(a,dtype=None,order=None)
其中,a为任意形式的输入参数,可以是列表、列表的元组、元组、元组的元组、元组的列表、多维数组;dtype为数据类型,可选;order可选,有'C'和'F'两个选项,分别代表行优先和列优先。
【例2-6】 利用numpy.asarray()函数实现从已有数组创建数组。
#将列表转换为ndarray
import numpy as np
x=[1,2,3]
a=np.asarray(x)
print('将列表转换为ndarray:',a)
#将元组转换为ndarray
x=(1,2,3)
a=np.asarray(x)
print('将元组转换为ndarray:',a)
#将元组列表转换为ndarray
x=[(1,2,3),(4,5)]
a=np.asarray(x)
print('将元组列表转换为ndarray:',a)
#设置了dtype参数
x=[1,2,3]
a=np.asarray(x,dtype=float)
print('设置了dtype参数:',a)
运行程序,输出如下。
将列表转换为ndarray:[1 2 3]
将元组转换为ndarray:[1 2 3]
将元组列表转换为ndarray:[(1,2,3)(4,5)]
设置了dtype参数:[1.2.3.]
2)numpy.frombuffer()函数
numpy.frombuffer()接受buffer输入参数,以流的形式读入转换的ndarray对象。函数的格式为:
numpy.frombuffer(buffer,dtype=float,count=-1,offset=0)
其中,buffer可以是任意对象,以流的形式读入;dtype为返回数组的数据类型,可选;count为读取的数据数量,默认为-1,读取所有数据;offset为读取的起始位置,默认为0。
【例2-7】 利用numpy.frombuffer()函数接受buffer输入转换数组。
import numpy as np
#buffer是字符串的时候,Python 3默认str是Unicode类型,所以要转成bytestring需要在原str
#前加上b
s=b'HelloWorld'
a=np.frombuffer(s,dtype='S1')
print(a)
运行程序,输出如下。
[b'H'b'e'b'l'b'l'b'o'b''b'W'b'o'b'r'b'l'b'd']
3)numpy.fromiter()函数
numpy.fromiter()从可迭代对象中建立ndarray对象,返回一维数组。函数的格式为:
numpy.fromiter(iterable,dtype,count=-1)
其中,iterable为可迭代对象;dtype为返回数组的数据类型;count为读取的数据数量,默认为-1,读取所有数据。
【例2-8】 利用numpy.fromiter()函数从对象中建立数组。
import numpy as np
#使用range函数创建列表对象
list=range(5)
it=iter(list)
#使用迭代器创建ndarray
x=np.fromiter(it,dtype=float)
print(x)
运行程序,输出如下。
[0.1.2.3.4.]
NumPy从数值范围创建数组主要有:创建指定范围的数组(numpy.arange())、创建指定范围的等差数列(numpy.linspace())、创建指定范围的等比数列(numpy.logspace())。
1)创建指定范围的数组
numpy包中使用arange()函数创建数值范围并返回ndarray对象,函数格式为:
numpy.arange(start,stop,step,dtype)
其中,start为起始值,默认为0;stop为结束值,必需,传一个值的时候虽然是赋值给了start,但却是一个结束值;step为步长,默认为1;dtype为数据类型,如果没有提供,则会使用输入数据的类型。
【例2-9】 利用numpy.arange()函数创建指定的数组。
import numpy as np
a=np.arange(5)
b=np.arange(5,dtype=float)
c=np.arange(10,20,2)
print('a:',a,'\n'
'b:',b,'\n'
'c:',c,'\n')
运行程序,输出如下。
a:[0 1 2 3 4]
b:[0.1.2.3.4.]
c:[10 12 14 16 18]
2)创建指定范围的等差数列
numpy.linspace()函数用于创建一个一维数组,数组是由一个等差数列构成的,函数格式为:
np.linspace(start,stop,num=50,endpoint=True,retstep=False,dtype=None)
其中,start为序列的起始值;stop为序列的终止值,如果endpoint为True,则该值包含于数列中;num为要生成的等步长的样本数量,默认为50;endpoint值为True时,数列中包含stop值,反之不包含,默认是True;retstep如果为True时,生成的数组中会显示间距,反之不显示;dtype为ndarray的数据类型。
【例2-10】 利用numpy.linspace()创建指定范围的等差数列。
#用到三个参数,设置起始点为1,终止点为10,数列个数为10
import numpy as np
a=np.linspace(1,10,10)
print('指定范围为10的10个数列:',a)
#设置元素全部是1的等差数列
a=np.linspace(1,1,10)
print('元素全部是1的等差数列:',a)
#endpoint设为False,不包含终止值
a=np.linspace(10,20,5,endpoint=False)
print('endpoint设为False,不包含终止值:',a)
#将endpoint设为True,则会包含20
a=np.linspace(1,10,10,retstep=True)
print('endpoint设为True的数列:',a)
#拓展例子
b=np.linspace(1,10,10).reshape([10,1])
print('拓展例子:',b)
运行程序,输出如下。
指定范围为10的10个数列:[ 1. 2. 3. 4. 5. 6. 7. 8. 9. 10.]
元素全部是1的等差数列:[1. 1. 1. 1. 1. 1. 1. 1. 1. 1.]
endpoint设为False,不包含终止值:[10. 12. 14. 16. 18.]
endpoint设为True的数列:(array([ 1., 2., 3., 4., 5., 6., 7., 8., 9., 10.]),1.0)
拓展例子:[[ 1.]
[ 2.]
[ 3.]
[ 4.]
[ 5.]
[ 6.]
[ 7.]
[ 8.]
[ 9.]
[ 10.]]
3)创建指定范围的等比数列
numpy.logspace()函数用于创建一个等比数列。函数格式为:
numpy.logspace(start,stop,num=50,endpoint=True,base=10.0,dtype=None)
其中,start为序列的起始值,为base**start;stop为序列的终止值,为base**stop;如果endpoint为True,该值包含于数列中;num为要生成的等步长的样本数量,默认为50;endpoint值为Ture时,数列中包含stop值,反之不包含,默认是True;base为对数log的底数;dtype为ndarray的数据类型。
值得注意的是,start和stop是数列的下标值,它们的底数是base。
【例2-11】 利用numpy.logspace()函数创建指定范围的等比数列。
import numpy as np
#默认底数是10
a=np.logspace(1.0,2.0,num=10)
print('默认底数是10的数列:',a)
#将对数的底数设置为2
a=np.logspace(0,9,10,base=2)
print('对数的底数设置为2的数列:',a)
运行程序,输出如下。
默认底数是10的数列:[10. 12.91549665 16.68100537 21.5443469 27.82559402
35.93813664 46.41588834 59.94842503 77.42636827 100. ]
对数的底数设置为2的数列:[1. 2. 4. 8. 16. 32. 64. 128. 256. 512.]
NumPy中包含一些函数用于处理数组,大概可分为以下几类:修改数组形状、翻转数组、修改数组维度、连接数组、分割数组、数组元素的添加与删除等。
在NumPy中提供了相关函数实现数组形状的修改,如表2-1所示。
表2-1 修改数组形状
1)numpy.reshape()函数
numpy.reshape()函数可以在不改变数据的条件下修改形状,函数的格式为:
numpy.reshape(arr,newshape,order='C')
其中,arr为要修改形状的数组;newshape为整数或者整数数组,新的形状应当兼容原有形状;order取'C'时按行,取'F'时按列,取'A'时按原顺序,取'K'时按元素在内存中的出现顺序。
【例2-12】 利用reshape()函数改变给定数组的形状。
import numpy as np
a=np.arange(8)
print('原始数组:',a)
b=a.reshape(4,2)
print('修改后的数组:',b)
运行程序,输出如下。
原始数组:[0 1 2 3 4 5 6 7]
修改后的数组:[[0 1]
[2 3]
[4 5]
[6 7]]
2)numpy.ndarray.flat()函数
numpy.ndarray.flat()是一个数组元素迭代器,下面直接通过实例来演示它的用法。
【例2-13】 利用numpy.ndarray.flat()更改数组的形状。
import numpy as np
a=np.arange(8).reshape(4,2)
print('原始数组:')
for row in a:
print(row)
#对数组中每个元素都进行处理,可以使用flat属性,该属性是一个数组元素迭代器
print('迭代后的数组:')
for element in a.flat:
print(element)
运行程序,输出如下。
原始数组:
[0 1]
[2 3]
[4 5]
[6 7]
迭代后的数组:
0
1
2
3
4
5
6
7
3)numpy.ndarray.flatten()
numpy.ndarray.flatten()返回一份数组副本,对副本所做的修改不会影响原始数组,函数的格式为:
ndarray.flatten(order='C')
其中,order取'C'时按行,取'F'时按列,取'A'时按原顺序,取'K'时按元素在内存中的出现顺序。
【例2-14】 利用numpy.ndarray.flatten()改变数组的形状。
import numpy as np
a=np.arange(8).reshape(2,4)
print('原数组:',a)
#默认按行
print('展开的数组:',a.flatten())
print('以F风格顺序展开的数组:',a.flatten(order= 'F'))
运行程序,输出如下。
原数组:[[0 1 2 3]
[4 5 6 7]]
展开的数组:[0 1 2 3 4 5 6 7]
以F风格顺序展开的数组:[0 4 1 5 2 6 3 7]
4)numpy.ravel()
numpy.ravel()展平的数组元素,顺序通常是“C风格”,返回的是数组视图,修改会影响原始数组。函数的格式为:
numpy.ravel(a,order='C')
其中,a为原始数据;order取'C'时按行,取'F'时按列,取'A'时按原顺序,取'K'时按元素在内存中的出现顺序。
【例2-15】 利用numpy.ravel()对所创建的数据进行展平。
import numpy as np
a=np.arange(8).reshape(2,4)
print('原数组:',a)
print('调用ravel函数之后:',a.ravel())
print('以F风格顺序调用ravel函数之后:',a.ravel(order= 'F'))
运行程序,输出如下。
原数组:[[0 1 2 3]
[4 5 6 7]]
调用ravel函数之后:[0 1 2 3 4 5 6 7]
以F风格顺序调用ravel函数之后:[0 4 1 5 2 6 3 7]
数组的翻转也是数组比较重要的操作之一,属于形状变化或维度变化的操作。可以通过以下方法实现,这些方法有属于ndarray的方法,也有属于NumPy的方法。除此以外,属性转置(ndarray.T())也可以实现数组行列翻转的功能,如表2-2所示。
表2-2 翻转数组函数
1)ndarray.transpose()函数
ndarray.transpose()函数用于返回转置轴的数组视图。函数的格式为:
ndarray.transpose(* axis)
其中,axis可选None,整数元组或者 n 个整数;返回值为数组的视图。
(1)axis=None或无参数时,反转轴的顺序。
(2)axis=整数数组,元组中第 j 个位置的 i 表示 a 的第 i 个轴变为 a .transpose()的第 j 个轴。
(3)axis= n 个整数,这种形式与元组形式功能相同。
【例2-16】 利用ndarray.transpose()函数返回数组视图。
import numpy as np
a=np.arange(12).reshape(3,4)
print('原数组:',a)
print('对换数组:',np.transpose(a))
运行程序,输出如下。
原数组:[[0 1 2 3]
[4 5 6 7]
[8 9 10 11]]
对换数组:[[0 4 8]
[1 5 9]
[2 6 10]
[3 7 11]]
2)ndarray.T()函数
数组中的属性(ndarray.T)是转置的意思,可以将数组进行行列交换。
【例2-17】 利用ndarray.T()对数组进行转置。
import numpy as np
a=np.arange(12).reshape(3,4)
print('原数组:',a)
print('转置数组:',a.T)
运行程序,输出如下。
原数组:[[0 1 2 3]
[4 5 6 7]
[8 9 10 11]]
转置数组:[[0 4 8]
[1 5 9]
[2 6 10]
[3 7 11]]
3)ndarray.moveaxis()函数
ndarray.moveaxis()实现将数组的轴移动到新位置。函数的格式为:
numpy.moveaxis(a,source,destination)
其中,a为接收ndarray,需要转动轴的数组;source为接收整数或者整数序列,要移动的轴的原始位置,必须是唯一的;destination为接收整数或者整数序列,每个原始轴的目标位置,也必须是唯一的。
【例2-18】 利用ndarray.moveaxis()函数将数组的轴移动到新位置。
import numpy as np
#创建了三维的ndarray
a=np.arange(8).reshape(2,2,2)
print('原数组:',a)
print('获取数组中一个值:',np.where(a==6))
print(a[1,1,0])
#将轴2滚动到轴0(宽度到深度)
print('调用rollaxis()函数:')
b=np.rollaxis(a,2,0)
print(b)
#查看元素a[1,1,0],即6的坐标,变成[0,1,1]
#最后一个0移动到最前面
print(np.where(b==6))
#将轴2滚动到轴1(宽度到高度)
print('调用rollaxis()函数:')
c=np.rollaxis(a,2,1)
print(c)
#查看元素a[1,1,0],即6的坐标,变成[1,0,1]
#最后的0和它前面的1对换位置
print(np.where(c==6))
运行程序,输出如下。
原数组:[[[0 1]
[2 3]]
[[4 5]
[6 7]]]
获取数组中一个值:(array([1],dtype=int64),array([1],dtype=int64),array([0],dtype=
int64))
6
调用rollaxis()函数:
[[[0 2]
[4 6]]
[[1 3]
[5 7]]]
(array([0],dtype=int64),array([1],dtype=int64),array([1],dtype=int64))
调用rollaxis()函数:
[[[0 2]
[1 3]]
[[4 6]
[5 7]]]
(array([1],dtype=int64),array([0],dtype=int64),array([1],dtype=int64))
4)numpy.swapaxis()函数
numpy.swapaxis()函数用于交换数组的两个轴,函数格式为:
numpy.swapaxis(arr,axis1,axis2)
其中,arr为输入的数组;axis1为对应第一个轴的整数;axis2为对应第二个轴的整数。
【例2-19】 利用numpy.swapaxis()函数交换数组的两个轴。
import numpy as np
#创建了三维的ndarray
a=np.arange(8).reshape(2,2,2)
print('原数组:',a)
#现在交换轴0(深度方向)到轴2(宽度方向)
print('调用 swapaxis()函数后的数组:')
print(np.swapaxis(a,2,0))
运行程序,输出如下。
原数组:[[[0 1]
[2 3]]
[[4 5]
[6 7]]]
调用swapaxis()函数后的数组:
[[[0 4]
[2 6]]
[[1 5]
[3 7]]]
5)numpy.rollaxis()函数
numpy.rollaxis()函数向后滚动特定的轴到一个特定位置,函数格式为:
numpy.rollaxis(arr,axis,start)
其中,arr为数组;axis为要向后滚动的轴,其他轴的相对位置不会改变;start默认为零,表示完整的滚动。
【例2-20】 利用numpy.rollaxis()函数向后滚动特定的轴到特定位置。
import numpy as np
#创建了三维的ndarray
a=np.arange(8).reshape(2,2,2)
print('原数组:',a)
print('获取数组中一个值:')
print(np.where(a==6))
print(a[1,1,0])
#将轴2滚动到轴0(宽度到深度)
print('调用rollaxis()函数:')
b=np.rollaxis(a,2,0)
print(b)
#查看元素a[1,1,0],即6的坐标,变成[0,1,1]
#最后一个0移动到最前面
print(np.where(b==6))
#将轴2滚动到轴1(宽度到高度)
print('调用rollaxis()函数:')
c=np.rollaxis(a,2,1)
print(c)
#查看元素a[1,1,0],即6的坐标,变成[1,0,1]
#最后的0和它前面的1对换位置
print(np.where(c==6))
运行程序,输出如下。
原数组:[[[0 1]
[2 3]]
[[4 5]
[6 7]]]
获取数组中一个值:
(array([1],dtype=int64),array([1],dtype=int64),array([0],dtype=int64))
6
调用rollaxis()函数:
[[[0 2]
[4 6]]
[[1 3]
[5 7]]]
(array([0],dtype=int64),array([1],dtype=int64),array([1],dtype=int64))
调用rollaxis()函数:
[[[0 2]
[1 3]]
[[4 6]
[5 7]]]
(array([1],dtype=int64),array([0],dtype=int64),array([1],dtype=int64))
在NumPy中,除了可以改变数组的形状外,还可以修改数组的维度,表2-3列出了相关函数。
表2-3 修改数组维度函数
1)numpy.broadcast()函数
numpy.broadcast()函数用于模仿广播机制。它返回一个对象,该对象封装了将一个数组广播到另一个数组的结果。该函数将两个数组作为输入参数。
【例2-21】 演示numpy.broadcast()函数的使用。
import numpy as np
x=np.array([[-1],[3],[2]])
y=np.array([4,5,6])
#对y广播x
b=np.broadcast(x,y)
#拥有iterator属性,基于自身组件的迭代器元组
print('对y广播x:')
r,c=b.iters
#Python 3.x为next(context),Python 2.x为context.next()
print(next(r),next(c))
print(next(r),next(c))
#shape属性返回广播对象的形状
print('广播对象的形状:')
print(b.shape)
#手动使用broadcast将x与y相加
b=np.broadcast(x,y)
c=np.empty(b.shape)
print('手动使用broadcast将x与y相加:')
print(c.shape)
c.flat=[u+v for(u,v)in b]
print('调用flat()函数:')
print(c)
#获得了和NumPy内建的广播支持相同的结果
print('x与y的和:')
print(x+y)
运行程序,输出如下。
对y广播x:
-1 4
-1 5
广播对象的形状:
(3,3)
手动使用broadcast将x与y相加:
(3,3)
调用flat()函数:
[[3.4.5.]
[7.8.9.]
[6.7.8.]]
x与y的和:
[[3 4 5]
[7 8 9]
[6 7 8]]
2)numpy.broadcast_to()函数
numpy.broadcast_to()函数将数组广播到新形状。它在原始数组上返回只读视图,通常不连续。如果新形状不符合NumPy的广播规则,该函数可能会抛出ValueError。
【例2-22】 演示numpy.broadcast_to()函数的用法。
import numpy as np
#将一行三列的数组广播到四行三列
a=np.arange(3).reshape(1,3)
print(a)
print(np.broadcast_to(a,(4,3)))
[[0 1 2]]
[[0 1 2]
[0 1 2]
[0 1 2]
[0 1 2]]
[[0]
[1]
[2]]
#将三行一列的数组广播到四行三列,报错
a=np.arange(3).reshape(3,1)
print(a)
print(np.broadcast_to(a,(4,3)))
ValueError:operands could not be broadcast together with remapped shapes[original- >
remapped]:(3,1)and requested shape(4,3)
3)numpy.expand_dims()函数
numpy.expand_dims()函数通过在指定位置插入新的轴来扩展数组形状,函数格式为:
numpy.expand_dims(arr,axis)
其中,arr为输入数组;axis为新轴插入的位置。
【例2-23】 利用numpy.expand_dims()函数扩展数组形状。
import numpy as np
x=np.array(([1,2],[3,4]))
print('数组x:')
print(x)
y=np.expand_dims(x,axis=0)
print('数组y:')
print(y)
print('数组x和y的形状:')
print(x.shape,y.shape)
#在位置1插入轴
y=np.expand_dims(x,axis=1)
print('在位置1插入轴之后的数组y:')
print(y)
print('x.ndim和y.ndim:')
print(x.ndim,y.ndim)
print('x.shape和y.shape:')
print(x.shape,y.shape)
运行程序,输出如下。
数组x:
[[1 2]
[3 4]]
数组y:
[[[1 2]
[3 4]]]
数组x和y的形状:
(2,2)(1,2,2)
在位置1插入轴之后的数组y:
[[[1 2]]
[[3 4]]]
x.ndim和y.ndim:
2 3
x.shape和y.shape:
(2,2)(2,1,2)
4)numpy.squeeze()函数
numpy.squeeze()函数从给定数组的形状中删除一维的条目,函数格式为:
numpy.squeeze(arr,axis)
其中,arr为输入数组;axis为整数或整数元组,用于选择形状中一维条目的子集。
【例2-24】 利用numpy.squeeze()函数在给定数组中删除一维的条目。
import numpy as np
x=np.arange(8).reshape(1,2,4)
print('数组x:')
print(x)
y=np.squeeze(x)
print('数组y:')
print(y)
print('数组x和y的形状:')
print(x.shape,y.shape)
运行程序,输出如下。
数组x:
[[[0 1 2 3]
[4 5 6 7]]]
数组y:
[[0 1 2 3]
[4 5 6 7]]
数组x和y的形状:
(1,2,4)(2,4)
连接意味着将两个或多个数组的内容放在单个数组中。在SQL中,基于键来连接表,而在NumPy中,按轴连接数组。NumPy提供了相关函数实现数组连接,如表2-4所示。
表2-4 连接数组
【例2-25】 综合演示数组的各种连接效果。
import numpy as np
arr1=np.array([[[-1,2],[-3,4]],[[-5,6],[-7,8]]])
arr2=np.array([[[9,10],[11,12]],[[13,14],[15,16]]])
"""级联拼接"""
arr=np.concatenate((arr1,arr2))#默认在第0维上进行数组的连接
arr_1=np.concatenate((arr1,arr2),axis=1)#axis指定拼接的维度,axis=1表示在第1维上对
#数组进行拼接
arr_2=np.concatenate((arr1,arr2),axis=2)#axis指定拼接的维度,axis=2表示在第2维上对
#数组进行拼接
"""堆栈拼接"""
arr_3=np.stack((arr1,arr2)) #默认在第0维上进行数组的连接
arr_4=np.stack((arr1,arr2),axis=1) #在第1维上进行数组的连接
arr_5=np.stack((arr1,arr2),axis=2) #在第2维上进行数组的连接
arr_6=np.stack((arr1,arr2),axis=3) #在第3维上进行数组的连接
"""其他方法"""
arr_7=np.hstack((arr1,arr2)) #按行堆叠,相当于级联axis=1的方法
arr_8=np.vstack((arr1,arr2)) #按列堆叠,相当于级联axis=0的方法
arr_9=np.dstack((arr1,arr2)) #按深度堆叠,相当于级联axis=2的方法
print("原始数组:")
print(arr1)
print("数组类型:",arr1.shape)
print()
print(arr2)
print("数组类型:",arr2.shape)
print()
print("使用concatenate()函数连接")
print()
print("默认在第0维上进行数组的连接")
print(arr)
print("数组类型:",arr.shape)
print()
print()
print("在第1维上进行数组的连接")
print(arr_1)
print("数组类型:",arr_1.shape)
print()
print("在第2维上进行数组的连接")
print(arr_2)
print("数组类型:",arr_2.shape)
print()
print("使用stack()函数连接")
print()
print("默认在第0维上进行数组的连接")
print(arr_3)
print("数组类型:",arr_3.shape)
print()
print("在第1维上进行数组的连接")
print(arr_4)
print("数组类型:",arr_4.shape)
print()
print("在第2维上进行数组的连接")
print(arr_5)
print("数组类型:",arr_5.shape)
print()
print("在第3维上进行数组的连接")
print(arr_6)
print("数组类型:",arr_6.shape)
print()
print("按行堆叠")
print(arr_7)
print("数组类型:",arr_7.shape)
print()
print("按列堆叠")
print(arr_8)
print("数组类型:",arr_8.shape)
print()
print("按高(深)堆叠")
print(arr_9)
print("数组类型:",arr_9.shape)
print()
运行程序,输出如下。
在NumPy中,数组可以进行水平、垂直或深度分割,相关的函数如表2-5所示。可以将数组分割成相同大小的子数组,也可以指定原数组中需要分割的位置。
表2-5 数组分割函数
1)numpy.split()函数
numpy.split()函数沿特定的轴将数组分割为子数组,函数格式为:
numpy.split(ary,indices_or_sections,axis)
其中,ary为被分割的数组;indices_or_sections如果是一个整数,就用该数平均切分,如果是一个数组,则沿轴的位置切分;axis为沿着哪个维度进行切分,默认为0,纵向切分(垂直方向),为1时,横向切分(水平方向)。
axis的值看作是x轴的值,为0时在y轴上即垂直方向,为1时在x轴上即水平方向。axis=0纵向切分,即对着y轴切开;axis=1横向切分,即对着x轴切开。
注意: indices_or_sections为整数平均切分时,原数组一定要能平均切分,如果不能则抛出异常。
【例2-26】 利用numpy.split()函数实现数组的分割。
x=np.arange(1,9)
print(x)
[1 2 3 4 5 6 7 8]
a=np.split(x,4)#传递整数4表示平均切分为4等份
print(a)
[array([1,2]),array([3,4]),array([5,6]),array([7,8])]
print(a[0])
[1 2]
print(a[1])
[3 4]
print(a[2])
[5 6]
print(a[3])
[7 8]
#传递数组进行分割
#[3,5]表示将原数组按索引0~2为一组,3~4为一组,5~末尾为一组切分
b=np.split(x,[3,5])
print(b)
[array([1,2,3]),array([4,5]),array([6,7,8])]
#split分割二维数组
a=np.array([[1,2,3],[4,5,6],[7,8,9],[10,11,12]])#创建二维数组
print(a)
[[1 2 3]
[4 5 6]
[7 8 9]
[10 11 12]]
r=np.split(a,2,axis=0)#整数2表示平均切分为2等份,axis=0表示纵向切分
print(r)
[array([[1,2,3],
[4,5,6]]),array([[7,8,9],
[10,11,12]])]
print(r[0])
[[1 2 3]
[4 5 6]]
print(r[1])
[[7 8 9]
[10 11 12]]
x,y=np.split(a,2,axis=0)
print(x)
[[1 2 3]
[4 5 6]]
print(y)
[[7 8 9]
[10 11 12]]
2)numpy.hsplit()函数
numpy.hsplit()函数可以水平分割数组,该函数有两个参数,第1个参数表示待分割的数组,第2个参数表示要将数组水平分割成几个小数组。
注意: 第2个参数值必须可以整除待分割数组的列数,即原数组必须可以平均等分,如果不能则抛出异常。
【例2-27】 利用numpy.hsplit()函数对数组进行水平分割。
import numpy as np
harr=np.floor(10 * np.random.random((2,6)))
print('原数组:')
print(harr)
print('拆分后数组:')
print(np.hsplit(harr,3))
运行程序,输出如下。
原数组:
[[5. 1. 2. 7. 6. 7.]
[4. 3. 8. 3. 7. 7.]]
拆分后数组:
[array([[5., 1.],
[4., 3.]]),array([[2., 7.],
[8., 3.]]),array([[6., 7.],
[7., 7.]])]
3)numpy.vsplit()函数
numpy.vsplit()函数可以垂直分割数组,该函数有两个参数,第1个参数表示待分割的数组,第2个参数表示将数组垂直分割成几个小数组。
【例2-28】 利用numpy.vsplit()函数分割数组。
import numpy as np
a=np.arange(16).reshape(4,4)
print('第一个数组:')
print(a)
print('竖直分割:')
b=np.vsplit(a,2)
print(b)
运行程序,输出如下。
第一个数组:
[[0 1 2 3]
[4 5 6 7]
[8 9 10 11]
[12 13 14 15]]
竖直分割:
[array([[0,1,2,3],
[4,5,6,7]]),array([[8, 9,10,11],
[12,13,14,15]])]
4)array_split()函数
对于一个长度为 L 的数组,该函数是这么拆的:前 L % n 个组的大小是 L // n +1,剩下组的大小是 L // n 。其中,“//”表示下取整(即np.floor()), n 代表划分后数组的个数。
【例2-29】 利用array_split()函数分割数组。
#生成要组合的两个数组
array1=np.arange(14).reshape(2,7)
ar=np.array_split(array1,2,axis=1)#按列分割成两份.此处若用np.split()则会报错.
print(ar)
运行程序,输出如下。
[array([[0, 1, 2, 3],
[7, 8, 9,10]]),array([[4, 5, 6],
[11,12,13]])]
在NumPy中对数组元素进行添加和删除操作,可以使用append()函数和insert()函数为数组添加元素,或者使用delete()函数返回删除了某个轴的子数组的新数组,以及使用unique()函数寻找数组内的唯一元素。
1)numpy.append()函数
numpy.append()函数是在数组的末尾添加元素,该函数会返回一个新数组,而原数组不变。函数的调用格式为:
numpy.append(arr,values,axis)
其中,参数arr表示输入的数组;values表示向arr数组添加的元素,values为数组,values数组列维度与arr数组列维度相同;axis表示沿着水平或竖直方向完成添加操作的轴,axis取0表示沿竖直方向操作,axis取1表示沿水平方向操作。
如果未提供axis值,在添加操作之前输入数组会被展开,values可以是单元素,也可以是任意数组,将values添加到arr数组后,该函数会返回一个新数组,而原数组不变。
【例2-30】 利用numpy.append()函数实现在数组末尾添加元素。
import numpy as np
a=np.array([[1,0,3],[4,5,7]])
print('第一个数组:')
print(a)
print('向数组添加元素:')
print(np.append(a,[7,8,9]))
print('沿轴0添加元素:')
print(np.append(a,[[7,8,9]],axis=0))
print('沿轴 1添加元素:')
print(np.append(a,[[5,5,5],[7,8,9]],axis=1))
运行程序,输出如下。
第一个数组:
[[1 0 3]
[4 5 7]]
向数组添加元素:
[1 0 3 4 5 7 7 8 9]
沿轴0添加元素:
[[1 0 3]
[4 5 7]
[7 8 9]]
沿轴1添加元素:
[[1 0 3 5 5 5]
[4 5 7 7 8 9]]
2)numpy.insert()函数
numpy.insert()函数在给定索引之前,沿给定轴在输入数组中插入值。该函数会返回一个新数组,原数组不变。函数的调用格式为:
numpy.insert(arr,obj,values,axis)
其中,参数arr表示输入的数组;obj表示在其之前插入值的索引;values表示向arr数组插入的值,values值可为单元素或values数组,并且values数组行维度与arr数组列维度相同;axis表示沿着水平或竖直方向完成插入操作的轴,axis取0表示沿竖直方向操作,即在arr数组行索引位于obj的位置处插入values值,axis取1表示沿水平方向操作,即在arr数组列索引位于obj的位置处插入values值。
如果未提供axis值,则在插入之前输入数组会被展开,values可以是单个元素,也可以是一维数组,将values插入obj的位置处,该函数会返回一个新数组,原数组不变。
另外,insert()函数如果传递了axis参数,则插入values值时,会以广播值数组作输入数组,即np.insert(arr,2,[9],axis=0),其中,values为[9],arr是2行4列数组,由于axis=0,则插入值的数组列维度与arr数组列维度相同,因此,插入值数组为1行4列的数组,也就是广播值数组[9,9,9,9]。
【例2-31】 利用numpy.insert()函数实现在数组中插入值。
import numpy as np
a=np.array([[1,4],[3,5],[5,8]])
print('第一个数组:')
print(a)
print('未传递axis参数。在删除之前输入数组会被展开.')
print(np.insert(a,3,[11,12]))
print('传递了axis参数。会广播值数组来配输入数组.')
print('沿轴0广播:')
print(np.insert(a,1,[11],axis=0))
print('沿轴 1广播:')
print(np.insert(a,1,11,axis= 1))
运行程序,输出如下。
第一个数组:
[[1 4]
[3 5]
[5 8]]
未传递axis参数。在删除之前输入数组会被展开.
[1 4 3 11 12 5 5 8]
传递了axis参数。会广播值数组来配输入数组.
沿轴0广播:
[[1 4]
[11 11]
[3 5]
[5 8]]
沿轴1广播:
[[1 11 4]
[3 11 5]
[5 11 8]]
3)numpy.delete()函数
numpy.delete()函数返回从输入数组中删除指定子数组的新数组,原数组不变。与insert()函数的情况一样,如果未提供轴参数,则输入数组将展开。函数的格式为:
numpy.delete(arr,obj,axis)
其中,参数arr表示输入的数组;obj是用整数或者整数数组表示的从输入数组中删除的子数组,obj可以用切片numpy.s_[start:end:step]表示要删除的子数组范围;axis表示沿着它删除给定子数组的轴,如果未提供axis值,则输入数组会被展开。
【例2-32】 利用numpy.delete()函数删除数组指定的子数组。
import numpy as np
a=np.arange(10).reshape(2,5)
print('第一个数组:')
print(a)
print('未传递axis参数。在插入之前输入数组会被展开.')
print(np.delete(a,5))
print('删除第二列:')
print(np.delete(a,1,axis=1))
print('包含从数组中删除的替代值的切片:')
a=np.array([1,2,3,4,5,6,7,8,9,10])
print(np.delete(a,np.s_[::2]))
运行程序,输出如下。
第一个数组:
[[0 1 2 3 4]
[5 6 7 8 9]]
未传递axis参数。在插入之前输入数组会被展开。
[0 1 2 3 4 6 7 8 9]
删除第二列:
[[0 2 3 4]
[5 7 8 9]]
包含从数组中删除的替代值的切片:
[2 4 6 8 10]
4)numpy.unique()函数
numpy.unique()函数用于去除数组中的重复元素。函数的调用格式为:
numpy.unique(arr,return_index,return_inverse,return_counts)
其中,arr为输入数组,如果不是一维数组则会展开;return_index如果为True,返回新列表元素在旧列表中的位置(下标),并以列表形式存储;return_inverse如果为True,返回旧列表元素在新列表中的位置(下标),并以列表形式存储;return_counts如果为True,返回去重数组中的元素在原数组中的出现次数。
【例2-33】 利用numpy.unique()函数去除数组中的重复元素。
import numpy as np
a=np.array([6,2,6,2,7,5,6,8,2,9])
print('第一个数组:')
print(a)
print('第一个数组的去重值:')
u=np.unique(a)
print(u)
print('去重数组的索引数组:')
u,indices=np.unique(a,return_index=True)
print(indices)
print('我们可以看到每个和原数组下标对应的数值:')
print(a)
print('去重数组的下标:')
u,indices=np.unique(a,return_inverse=True)
print(u)
print('下标为:')
print(indices)
print('使用下标重构原数组:')
print(u[indices])
print('返回去重元素的重复数量:')
u,indices=np.unique(a,return_counts=True)
print(u)
print(indices)
运行程序,输出如下。
第一个数组:
[6 2 6 2 7 5 6 8 2 9]
第一个数组的去重值:
[2 5 6 7 8 9]
去重数组的索引数组:
[1 5 0 4 7 9]
我们可以看到每个和原数组下标对应的数值:
[6 2 6 2 7 5 6 8 2 9]
去重数组的下标:
[2 5 6 7 8 9]
下标为:
[2 0 2 0 3 1 2 4 0 5]
使用下标重构原数组:
[6 2 6 2 7 5 6 8 2 9]
返回去重元素的重复数量:
[2 5 6 7 8 9]
[3 1 3 1 1 1]