入门Numpy
一.NumPy的引入
标准安装的Python中用列表(list)保存一组值,可以用来当作数组使用,不过由于列表的元素可以是任何对象,因此列表中所保存的是对象的指针。这样为了保存一个简单的[1,2,3],需要有3个指针和三个整数对象。对于数值运算来说这种结构显然比较浪费内存和CPU计算时间。
此外Python还提供了一个array模块,array对象和列表不同,它直接保存数值,和C语言的一维数组比较类似。但是由于它不支持多维,也没有各种运算函数,因此也不适合做数值运算。
NumPy的诞生弥补了这些不足,NumPy提供了两种基本的对象:ndarray(N-dimensional array object)和 ufunc(universal function object)。ndarray(下文统一称之为数组)是存储单一数据类型的多维数组,而ufunc则是能够对数组进行处理的函数。
Examples:
Python中的列表中的元素不能直接相加减。
例如:
>>>a=[1,2,3]
>>>b=[1,2,3]
>>>a+b
[1, 2, 3, 1, 2, 3]
最佳的方式是将列表转换成Python中的科学计算包numpy包的array类型,再进行加减。
import numpy as np
>>>a = np.array([1,2,3,4])
.>>>b = np.array([7,8,9,10])
.>>>a + b
array([ 8, 10, 12, 14])
二.ndarray对象
import numpy as np
1.手动创建
(1)首先需要创建数组才能对其进行其它操作。
1)我们可以通过给array函数传递Python的序列对象创建数组
>>> a = np.array([1, 2, 3, 4])
>>> b = np.array((5, 6, 7, 8))
2).如果传递的是多层嵌套的序列,将创建多维数组(下例中的变量c):
>>> c = np.array([[1, 2, 3, 4],[4, 5, 6, 7], [7, 8, 9, 10]])
>>> c
array([[1, 2, 3, 4], [4, 5, 6, 7], [7, 8, 9, 10]])
(2)数组的大小可以通过其shape属性获得
>>> a.shape
(4,)
>>> c.shape
(3, 4)
数组a的shape只有一个元素,因此它是一维数组。
数组c的shape有两个元素,因此它是二维数组,其中第0轴的长度为3,第1轴的长度为4。
1).可以通过修改数组的shape属性,在保持数组元素个数不变的情况下,改变数组每个轴的长度。
下面的例子将数组c的shape改为(4,3),注意从(3,4)改为(4,3)并不是对数组进行转置,而只是改变每个轴的大小,数组元素在内存中的位置并没有改变:
>>> c.shape = 4,3
>>> c
array([[ 1, 2, 3], [ 4, 4, 5], [ 6, 7, 7], [ 8, 9, 10]])
2).当某个轴的元素为-1时,将根据数组元素的个数自动计算此轴的长度
因此下面的程序将数组c的shape改为了(2,6):
>>> c.shape = 2,-1
>>> c
array([[ 1, 2, 3, 4, 4, 5], [ 6, 7, 7, 8, 9, 10]])
3).使用数组的reshape方法,可以创建一个改变了尺寸的新数组,原数组的shape保持不变:
>>> d = a.reshape((2,2))
>>>d
array([[1, 2],
[3, 4]])
>>>a
array([1, 2, 3, 4])
数组a和d其实共享数据存储内存区域,因此修改其中任意一个数组的元素都会同时修改另外一个数组的内容:
>>> a[1] = 100 # 将数组a的第一个元素改为100
>>> d # 注意数组d中的2也被改变了
array([[ 1, 100], [ 3, 4]])
>>>a
array([ 1, 100, 3, 4])
(3)数组的元素类型可以通过dtype属性获得。
上面例子中的参数序列的元素都是整数,因此所创建的数组的元素类型也是整数,并且是32bit的长整型。可以通过dtype参数在创建时指定元素类型:
>>> np.array([[1, 2, 3, 4],[4, 5, 6, 7], [7, 8, 9, 10]], dtype=np.float)
array([[ 1., 2., 3., 4.], [ 4., 5., 6., 7.], [ 7., 8., 9., 10.]])
>>> np.array([[1, 2, 3, 4],[4, 5, 6, 7], [7, 8, 9, 10]], dtype=np.complex)
array([[ 1.+0.j, 2.+0.j, 3.+0.j, 4.+0.j], [ 4.+0.j, 5.+0.j, 6.+0.j, 7.+0.j], [ 7.+0.j, 8.+0.j, 9.+0.j, 10.+0.j]])
上面的例子都是先创建一个Python序列,然后通过array函数将其转换为数组,这样做显然效率不高。因此NumPy提供了很多专门用来创建数组的函数。
2.函数创建
(1)np.zeros(shape, dtype=float, order='C')
按照给定的shape(数组维度)和type(元素类型)建立元素都是0的一维或多维数组
shape :int or sequence of ints
dtype :data-type, optional e.g., `numpy.int8`. Default is`numpy.float64`.
Examples
>>>np.zeros(3)
array([ 0., 0., 0.])
>>>np.zeros((3,2))
array([[ 0., 0.],
[ 0., 0.],
[ 0., 0.]])
(2)np.empty(shape, dtype=float, order='C')
按照给定的shape和type返回一个新数组,没有初始化的项,不像“zeros”,不会设置元素值为0
和np.zeros都可用来初始化数组
Examples
>>>np.empty(2)
array([ 2.48675631e-316, 2.48960707e-316])
>>> np.empty([2, 2])
array([[ -9.74499359e+001, 6.69583040e-309],
[ 2.13182611e-314, 3.06959433e-309]]) #random
(3)np.tile(A, reps)
构建一个数组:重复A元素 reps次来构建一个数组
>>>target=np.array([1, 0.2])
>>>np.tile(target, (4, 1))
array([[ 1. , 0.2],
[ 1. , 0.2],
[ 1. , 0.2],
[ 1. , 0.2]])
>>>np.tile(target, 4)
array([ 1. , 0.2, 1. , 0.2, 1. , 0.2, 1. , 0.2])
(4)np.randint(low, high=None, size=None)
返回一个随机整数数组,元素的大小是服从左闭右开区间[`low`, `high`)上的‘离散均匀分布’,数组维度为size
Parameters
low : 整数 , 最小的数,除非high是None,此时low是最大的数,元素的范围就是在区间[0,'low')
high : 整数 ,最大的数,是可选的参数
size : 整数或者一个整数元组, 是可选的,代表了构建数组的维度, I比如:`(m, n, k)``, 表示``m * n * k``的数组 . 默认是None,此时返回单个的值
Examples
>>> np.random.randint(2, size=10)
array([1, 0, 0, 0, 1, 1, 0, 0, 1, 0])
>>> np.random.randint(1, size=10)
array([0, 0, 0, 0, 0, 0, 0, 0, 0, 0])
Generate a 2 x 4 array of ints between 0 and 4, inclusive:
>>> np.random.randint(5, size=(2, 4))
array([[4, 0, 2, 1],
[3, 2, 2, 0]])
(5)np.sum(a, axis=None, dtype=None, out=None, keepdims=False):
按照给定的维度求数组的元素和
Parameters
a : 类似于array,需要求和的元素
axis :求和的维度,`axis` 的默认值是 `None,是对所有的元素进行求和
Examples
>>> np.sum([0.5, 1.5])
2.0
>>> np.sum([0.5, 0.7, 0.2, 1.5], dtype=np.int32)
1
>>> np.sum([[0, 1], [0, 5]])
6
>>> np.sum([[0, 1], [0, 5]], axis=0)
array([0, 6])
>>> np.sum([[0, 1], [0, 5]], axis=1)
array([1, 5])
不使用numpy库的sum函数对二维list/array/matrix按行、列求和:
>>> s=array([[1, 2, 3], [0, 0, 1], [1, 0, 1], [0, 1, 0]])
>>> s
array([[1, 2, 3],
[0, 0, 1],
[1, 0, 1],
[0, 1, 0]])
>>> lin = map(sum,s)..........................在行方向上求和
>>> lin
[6, 1, 2, 1]
>>> col = map(sum,zip(*s))....................在列方向上求和
>>> col
[2, 3, 5]
可以看出:numpy确实方便好用
(6)np.multiply(x1, x2[, out])
多个参数的对应元素相乘,对于array来说,返回的就是对应元素相乘后的array,多于matrix,返回的就是对应元素相乘后的matrix
Parameters
x1, x2 : 类似于array,参与相乘的array.
Examples
>>>x=np.mat([[1,2,3],[2,3,4]])
>>>y=np.mat([[1,2,4],[2,1,1]])
>>>np.multiply(x,y)
matrix([[ 1, 4, 12],
[ 4, 3, 4]])
(7)np.dot(a, b, out=None)
对于一维的array,返回值是两个array的内积,等价于:sum([i*j for i,j in zip(a,b)])
对于二维array(包含matrix)来说,等价于矩阵相乘
(8)np.nonzero(a)
对于一维array来说,返回非零元素的索引
对于二维或多维的array来说,返回的是一个元组,元组的每个元素是array,每个array是a的非零元素的每一维取值
Parameters
a : 类似于array
Examples
>>> x = np.eye(3)
>>> x
array([[ 1., 0., 0.],
[ 0., 1., 0.],
[ 0., 0., 1.]])
>>> np.nonzero(x)
(array([0, 1, 2]), array([0, 1, 2]))表示非零元素有三个,第一个是第一行第一列的,第二个是第二行
a[nonzero(a)]得到了a中所有非零元素
>>>x[nonzero(x)]
array([ 1., 1., 1.])
transpose(nonzero(a))返回一个二维数组,每个元素是a中非零元素的所有方向的维度
>>>np.transpose(np.nonzero(y))
array([[0, 0],
[1, 1],
[2, 2]], dtype=int64)
(9)np.insert(arr, obj, values, axis=None):
沿着给定的轴在给定的索引前插入相应的值
Paramaters:
arr : 类似于array
obj : 整数或者整数序列,是在值被插入之前定义索引的对象
values :类似于array,插入到arr里的值,如果值的类型不同于arr,那么会被转化为arr的类型,values会被重塑使得arr[...,obj,...] = values是合法的
axis : 整数,可选的,沿着这个轴插入values,如果是None,那么arr会首先被摊平
Examples:
>>>x = np.array([[1, 2, 2, 0, 1], [3, 4, 2, 0, 1], [2, 5, 1, 0, 2], [2, 3, 5, 1, 3], [1, 4, 2, 3, 1], [3, 4, 2, 2, 1]])
>>>x
array([[1, 2, 2, 0, 1],
[3, 4, 2, 0, 1],
[2, 5, 1, 0, 2],
[2, 3, 5, 1, 3],
[1, 4, 2, 3, 1],
[3, 4, 2, 2, 1]])
>>>x_theta0 = np.ones(x.shape[0])
>>>x_theta0
array([ 1., 1., 1., 1., 1., 1.])
>>>design_matrix = np.insert(x, 0, values=x_theta0, axis=1)
>>>design_matrix
array([[1, 1, 2, 2, 0, 1],
[1, 3, 4, 2, 0, 1],
[1, 2, 5, 1, 0, 2],
[1, 2, 3, 5, 1, 3],
[1, 1, 4, 2, 3, 1],
[1, 3, 4, 2, 2, 1]])
(10)np.random.randn(d0, d1, ..., dn)
从“标准正态”分布返回一个样本
Parameters
d0, d1, ..., dn :整数,可选的,是返回的array的各个维度的维数,都是正数,如果没有参数被给,那么会返回一个浮点数
Examples:
>>>np.random.randn(2, 1)
array([[-0.82557488],
[-1.5134927 ]])
3.array布尔切片
(1)一维切片
>>> x=np.random.rand(10)
>>> x
array([ 0.5993579 , 0.68693925, 0.74380945, 0.40993085, 0.72345401,0.64499497, 0.48715468, 0.80924589, 0.43362779, 0.06554248])
1)array与某个元素进行比较
>>> x>0.5
array([ True, True, True, False, True, True, False, True, False, False], dtype=bool)
>>> x[x>0.5] #将它当做索引传回原数组,只获取那些>0.5的
array([ 0.5993579 , 0.68693925, 0.74380945, 0.72345401, 0.64499497,0.80924589])
2)两个array的对应位置元素作比较
>>> a=np.array([1,2,3])
>>> b=np.array([3,2,1])
>>> a>b
array([False, False, True], dtype=bool)
>>> a[a==b] #获取一样的元素
array([2])
3)all&any
>>> np.all(x<1) #测试x<1所返回的数组(传给all)中所有元素是否都等价True
True
>>> np.any([1,2,3,4]) #如果传入的数组中有至少一个元素等价True都返回True
True
(2)二维切片
>>>dataMatrix=np.matrix([[1., 2.1],
[2., 1.1],
[1.3, 1.],
[1., 1.],
[2., 1.]])
>>>retArray = np.ones((np.shape(dataMatrix)[0], 1))
>>>retArray
array([[ 1.],
[ 1.],
[ 1.],
[ 1.],
[ 1.]])
1)二维切片[i][j]
>>>dataMatrix[:, 0] <= 1.6
matrix([[ True],
[False],
[ True],
[ True],
[False]], dtype=bool)
2)二维布尔切片
>>>retArray[dataMatrix[:, 0] <= 1.6] = -1.0
>>>retArray
array([[-1.],
[ 1.],
[-1.],
[-1.],
[ 1.]])
三.对比matrix和array
1.简述区别
Numpy matrices必须是2维的,但是numpy arrays (ndarrays) 可以是多维的(1D,2D,3D····ND).
Matrix是Array的一个小的分支,包含于Array。所以matrix 拥有array的所有特性。在numpy中matrix的主要优势是:相对简单的乘法运算符号
2.操作符运算
(1)array数组
numpy中最基本(默认)的类型是array,他的相关操作都是按元素操作的即用作数值计算当中(按元素操作有+,-,,/,*等)。
Examples:
import numpy as np
>>>np.array([1])+np.array([2])
array([3])
>>>np.array([1])-np.array([2])
array([-1])
>>>np.array([1])*np.array([2.0])
array([ 2.])
>>>np.array([1])/np.array([2])
array([0])
>>>np.array([1])/np.array([2.0])
array([ 0.5])
>>>x=np.array([1,2,3])
>>>y=np.array([3,4,5])
>>>x*y
array([ 3, 8, 15])
>>>np.multiply(x,y)
array([ 3, 8, 15])
>>>np.dot(x,y)
26
array的操作总结如下:
1.*和multiply:是两个array的对应元素的相乘
2.dot对于一维array是计算内积,对于多维是相当于矩阵相乘
3.**是array的对应元素做乘方
4. .T表示转置
5. array转换为matrix:asmatrix()或者np.matrix()
6.多数numpy函数返回的是array类型,不是matrix类型
(2)matrix矩阵
在numpy中的特殊类型,是作为array的子类出现,所以继承了array的所有特性并且有自己的特殊的地方,专门用来处理线性代数操作
Examples:
>>>x=np.matrix(x)
>>>y=np.matrix(y)
>>>x*y
Traceback (most recent call last): File "C:\Anaconda2\lib\site-packages\IPython\core\interactiveshell.py", line 2885, in run_code exec(code_obj, self.user_global_ns, self.user_ns) File "", line 1, inx*y
File "C:\Anaconda2\lib\site-packages\numpy\matrixlib\defmatrix.py", line 343, in __mul__
return N.dot(self, asmatrix(other))
ValueError: shapes (1,3) and (1,3) not aligned: 3 (dim 1) != 1 (dim 0)
matrix的操作总结如下:
1.*和dot表示是两个矩阵的相乘,满足矩阵相乘原则。
2.multiply表示两个matrix的对应元素的相乘
3.**是矩阵的乘方(power),和array的乘方不一样,不是单纯的每个元素做乘方,而是n个同样的矩阵相乘,当然前提矩阵能做乘方必须是方阵
4.除/则表示对于两个matrix的对应元素的相除
5. .H,.A,.I表示共轭,转置,逆矩阵。
6.matrix转换为array用asarray()
(3)array和matrix的一个很难理解的点
这里会涉及到rank的概念,在线性代数(math)rank表示秩,但是必须明确的是在numpy里rank不是表示秩的概念,是表示维数的概念
array要求秩为1(N*1,1*N等)或者大于2
matrix要求秩必须为2(rank必须为2)
下面通过例子来理解ndim和size:
>>> a#一维array
array([1, 2])
>>> a.size
2
>>> a.ndim
1
>>> b#二维array
array([[1, 2],
[2, 3]])
>>> b.size
4
>>> b.ndim
2
>>> c#small matrix
matrix([[1, 2, 3, 4],
[2, 3, 4, 5]])
>>> c.size
8
>>> c.ndim
2
>>> e#big matrix
matrix([[1, 2, 3, 4],
[2, 3, 4, 5],
[3, 4, 5, 6]])
>>>e.size
12
>>> e.ndim
2
总结:
1.ndim就是求的是rank,所以会发现matrix的都是2,但是array的就会存在差异,需要计算等。
2.size返回的是元素的个数