Numpy
numpy(Numerical Python)是 Python 语言的一个扩展程序库,支持大量的维度数组与矩阵运算,此外也针对数组运算提供大量的数学函数库。它包含:
- ndarray, 一个有效的多维数组,能提供以数组为导向的快速数值计算和灵活的广播功能(broadcasting)
- 便利的数学函数
- 用于读取/写入(reading/writing)数据到磁盘的便利工具
- 线性代数,随机数生成,傅里叶变换能力
- 整合 C/C++/Fortran 代码的工具
import numpy as np #默认的常规操作,用起来方便
ndarrays——n维数组
创建n维数组
使用array函数,输入一个序列即可,比如list(根据维数需求可以嵌套列表),array还可以指定数据类型:
[In]:
data = [[1, 2, 3, 4], [5, 6, 7, 8]] #嵌套列表
arr = np.array(data2)
arr
[out]:
array([[1, 2, 3, 4],
[5, 6, 7, 8]])
[In]:arr1 = np.array([1, 2, 3], dtype=np.float64)
zeros,ones可以创建全为0和全为1的数组,还可以在一个tuple里指定shape;
eye可以创建单位矩阵
empty并不能保证返回所有是0的数组,某些情况下,会返回为初始化的垃圾数值;
arange是一个数组版的range函数:
[In]:np.zeros(10)
[Out]:array([0., 0., 0., 0., 0., 0., 0., 0., 0., 0.])
[In]:np.zeros((3, 6))
[Out]:array([[0., 0., 0., 0., 0., 0.],
[0., 0., 0., 0., 0., 0.],
[0., 0., 0., 0., 0., 0.]])
#维数是作为一个参数输入,因此需要加括号将其作为一个整体
[In]:np.empty((2, 3, 2))
[Out]:array([[[1.32696695e-311, 2.47032823e-322],
[0.00000000e+000, 0.00000000e+000],
[0.00000000e+000, 2.92966904e-033]],
[[6.20490760e-091, 2.21464435e+160],
[2.34085430e-057, 9.05625529e-043],
[3.99910963e+252, 2.69776571e+184]]])
[In]:np.arange(15)
[Out]:array([ 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14])
维度,数据类型
shape,表示维度大小;
dtype,表示data type;
[In]:arr.shape
[Out]:(2,4)
[In]:arr.dtype
[Out]:dtype('int32')
astype,用来来转换类型:
a. 如果是把float变为int,小数点后的部分会被丢弃(向下取整)
b. astype可以把string里的数字变为实际的数字,但是要十分注意numpy.string_类型,这种类型的长度是固定的,所以可能会直接截取部分输入而不给警告。
c. astype里面可以直接用别的数组的类型,如arr1.astype(arr.dtype)
[In]:arr = arr.astype(np.float64)
arr.dtype
[Out]:dtype('float64')
[In]:numeric_strings = np.array(['1.25', '-9.6', '42'], dtype=np.string_)
numeric_strings
[Out]:array([b'1.25', b'-9.6', b'42'], dtype='|S4')
[In]:numeric_strings.astype(float)
[Out]:array([ 1.25, -9.6 , 42. ])
数组计算与赋值,访问单一元素
任何两个大小相等的数组之间的运算,都是element-wise(点对点),如+,-,*,/,**等等。
如果想计算矩阵间的乘法,可以使用np.dot()
标量和数组都能赋给数组元素(如arr[1]),赋值标量时相当于给数组某一维或者某几个维度的所有元素赋值(如arr[1]=9)。
访问单一元素有两种方法:
arr[1][1]
arr[1,1]
6
索引
索引和之前讲过的差不多,规则都是前闭后开,从零开始。
- 布尔值作为索引
[In]:names = np.array(['Bob', 'Joe', 'Will', 'Bob', 'Will', 'Joe', 'Joe'])
data = np.random.randn(7, 4)
data[names == 'Bob']
{out]:array([[ 0.93712697, 0.63762909, -1.65453584, -0.73713961],
[-0.81897648, -0.98178569, -0.14503704, 0.80626929]])
#此处是索引了等于Bob的数据行,可以额外添加列的数值要求
多个条件要使用布尔运算符&,|,~等。但是要注意用布尔索引总是会返回一份新创建的数据,原本的数据不会被改变。 如果要更改值也很简单,如将负数变为零:
data[data < 0] = 0
- 多维索引数组,能选出由一维数组中的元素,通过在每个tuple中指定索引
[In]:arr = np.arange(32).reshape((8, 4)) #理解成1维,改变形状为2维
arr
{out]:array([[ 0, 1, 2, 3],
[ 4, 5, 6, 7],
[ 8, 9, 10, 11],
[12, 13, 14, 15],
[16, 17, 18, 19],
[20, 21, 22, 23],
[24, 25, 26, 27],
[28, 29, 30, 31]])
[In]:arr[[1, 5, 7, 2], [0, 3, 1, 2]] #逗号左边对应行,右边对应列
{out]:array([ 4, 23, 29, 10])
切片
- 切片的性质
[In]:arr = np.arange(10)
arr[5:8] = 12
arr
[Out]:array([ 0, 1, 2, 3, 4, 12, 12, 12, 8, 9])
这里把12赋给arr[5:8],其实用到了broadcasted。
这里有一个比较重要的概念需要区分,python内建的list与numpy的array有个明显的区别,这里array的切片后的结果只是一个views(视图),用来代表原有array对应的元素,而不是创建了一个新的array。但 list里的切片是产生了一个新的list。
也就是说,当改变array的切片时,原数组也会受到影响,但python中的列表(list)则不会受到切片影响:
[In]:arr_slice = arr[5:8]
arr_slice[1] = 12345
arr
[Out]:array([ 0, 1, 2, 3, 4, 12, 12345, 12, 8, 9])
[In]:x=[1,2,3,4,5]
y=x
y[1]=9
x
[Out]:[1, 9, 3, 4, 5]
#这种情况下相当于同时改变了x,y的第二个值
[In]:z=y[1:4]
z[1]=8
y
[Out]:[1, 9, 3, 4, 5]
#z是y的切片,因此y本身不受z改变的影响
如果想要复制,可以使用copy()方法,比如arr[5:8].copy()进行赋值。
- 多维数组的切片
多维数组的切片是沿着行来处理的。所以,数组中的切片,是要沿着设置的axis来处理的。
当然,给定多个索引后,也可以使用复数切片:
[In]:arr2d = np.array([[1, 2, 3], [4, 5, 6], [7, 8, 9]])
[Out]:array([[1, 2, 3],
[4, 5, 6],
[7, 8, 9]])
[In]:arr2d[:2, 1:]
[Out]:array([[2, 3],
[5, 6]])
#前两行,第二列之后
转置
以下方法均只返回一个view,而不是新建一个数组。
- T属性
arr.T
- transpose
首先要明确,多维数组的第一个方括号“[]”为 0轴 ,第二个方括号为1轴,以此类推。
对于二维数组,arr.transpose默认是转置,但是当维数更高时,会接受由轴数字组成的tuple,来交换轴。以三维为例:
易知transpose可以通过指定轴的顺序从而交换轴位置
[In]:arr = np.arange(16).reshape((2, 2, 4))
arr
[Out]:array([[[ 0, 1, 2, 3],
[ 4, 5, 6, 7]],
[[ 8, 9, 10, 11],
[12, 13, 14, 15]]])
[In]:arr.transpose(( 1,0,2))
[Out]:array([[[ 0, 1, 2, 3],
[ 8, 9, 10, 11]],
[[ 4, 5, 6, 7],
[12, 13, 14, 15]]])
- swapaxes
ndarray有方法叫做swapaxes, 这个方法取两个axis值,并交换这两个轴:
[In]:arr.swapaxes(1, 2) # 直交换第二个轴和最后一个轴
[Out]:array([[[ 0, 4],
[ 1, 5],
[ 2, 6],
[ 3, 7]],
[[ 8, 12],
[ 9, 13],
[10, 14],
[11, 15]]])
常用函数
取整、取小数
函数 | 说明 |
---|---|
np.around() | 四舍五入,可以指定精度 |
np.round() | 同上 |
np.rint() | 将x中各元素四舍五入取整 |
np.ceil() | 将x中各元素向上取整 |
np.floor() | 将x中各元素向下取整 |
np.modf() | 返回两个ndarray,分别为x的小数部分和x的整数部分 |
np.trunc() | 返回整数部分 |
np.fix() | 返回整数部分 |
数组合并
- np.concatenate
np.concatenate([a,b],axis=0)
第一个参数是要合并的数组,用中括号包括在一起
第二个参数是轴,指按照哪个方向进行合并
- np.vstack()、np.hstack()
语法:
np.vstack((arr1, arr2))
np.vstack()纵向合并(样本合并)
np.hstack()横向合并(变量合并)
axis
numpy中很多函数都会有axis这个参数,axis=i可以理解为第i个变化的下标的方向。例如:二维数组,axis=1即表示列变化的方向,所以是对一整行做操作
nparray和list转换
a=[[1,2],[3,4]]
a=np.array(a)
a.tolist()