Numpy简介
1.Numpy是什么
非常easy。Numpy是Python的一个科学计算的库。提供了矩阵运算的功能,其一般与Scipy、matplotlib一起使用。事实上,list已经提供了类似于矩阵的表示形式,只是numpy为我们提供了很多其它的函数。
假设接触过matlab、scilab。那么numpy非常好入手。
在下面的代码演示样例中。总是先导入了numpy:(通用做法import numpu as np 简单输入)
>>> import numpy as np
>>> print np.version.version
1.6.2
2. 多维数组
多维数组的类型是:numpy.ndarray。
使用numpy.array方法
以list或tuple变量为參数产生一维数组:
>>> print np.array([1,2,3,4])
[1 2 3 4]
>>> print np.array((1.2,2,3,4))
[ 1.2 2. 3. 4. ]
>>> print type(np.array((1.2,2,3,4)))
<type 'numpy.ndarray'>
以list或tuple变量为元素产生二维数组或者多维数组:
>>> x = np.array(((1,2,3),(4,5,6)))
>>> x
array([[1, 2, 3],
[4, 5, 6]])
>>> y = np.array([[1,2,3],[4,5,6]])
>>> y
array([[1, 2, 3],
[4, 5, 6]])
numpy数据类型设定与转换
numpy ndarray数据类型能够通过參数dtype 设定。并且能够使用astype转换类型。在处理文件时候这个会非常有用。注意astype 调用会返回一个新的数组,也就是原始数据的一份拷贝。
numeric_strings2 = np.array(['1.23','2.34','3.45'],dtype=np.string_)
numeric_strings2
Out[32]:
array(['1.23', '2.34', '3.45'],
dtype='|S4')
numeric_strings2.astype(float)
Out[33]: array([ 1.23, 2.34, 3.45])
numpy索引与切片
index 和slicing :第一数值类似数组横坐标。第二个为纵坐标
>>> x[1,2]
6
>>> y=x[:,1]
>>> y
array([2, 5])
涉及改变相关问题,我们改变上面y是否会改变x?这是特别须要关注的。
>>> y
array([2, 5])
>>> y[0] = 10
>>> y
array([10, 5])
>>> x
array([[ 1, 10, 3],
[ 4, 5, 6]])
通过上面能够发现改变y会改变x ,因而我们能够判断,y和x指向是同一块内存空间值,系统没有为y 新开辟空间把x值赋值过去。
arr = np.arange(10)
arr
Out[45]: array([0, 1, 2, 3, 4, 5, 6, 7, 8, 9])
arr[4]
Out[46]: 4
arr[3:6]
Out[47]: array([3, 4, 5])
arr[3:6] = 12
arr
Out[49]: array([ 0, 1, 2, 12, 12, 12, 6, 7, 8, 9])
如上所看到的:当将一个标量赋值给切片时。该值会自己主动传播整个切片区域,这个跟列表最重要本质差别,数组切片是原始数组的视图,视图上不论什么改动直接反映到源数据上面。
思考为什么这么设计? Numpy 设计是为了处理大数据,假设切片採用数据复制话会产生极大的性能和内存消耗问题。
假如说须要对数组是一份副本而不是视图能够例如以下操作:
arr_copy = arr[3:6].copy()
arr_copy[:]=24
arr_copy
Out[54]: array([24, 24, 24])
arr
Out[55]: array([ 0, 1, 2, 12, 12, 12, 6, 7, 8, 9])
再看下对list 切片改动
l=range(10)
l
Out[35]: [0, 1, 2, 3, 4, 5, 6, 7, 8, 9]
l[5:8] = 12
Traceback (most recent call last):
File "<ipython-input-36-022af3ddcc9b>", line 1, in <module>
l[5:8] = 12
TypeError: can only assign an iterable
l1= l[5:8]
l1
Out[38]: [5, 6, 7]
l1[0]=12
l1
Out[40]: [12, 6, 7]
l
Out[41]: [0, 1, 2, 3, 4, 5, 6, 7, 8, 9]
这里设计到python 中深浅拷贝,当中切片属于浅拷贝,详细參考:
python深浅拷贝
多维数组索引、切片
arr2d = np.arange(1,10).reshape(3,3)
arr2d
Out[57]:
array([[1, 2, 3],
[4, 5, 6],
[7, 8, 9]])
arr2d[2]
Out[58]: array([7, 8, 9])
arr2d[0][2]
Out[59]: 3
arr2d[0,2]
Out[60]: 3
布尔型索引
这样的类型在实际代码中出现比較多,关注下。
names = np.array(['Bob','joe','Bob','will'])
names == 'Bob'
Out[70]: array([ True, False, True, False], dtype=bool)
data
Out[73]:
array([[ 0.36762706, -1.55668952, 0.84316735, -0.116842 ],
[ 1.34023966, 1.12766186, 1.12507441, -0.68689309],
[ 1.27392366, -0.43399617, -0.80444728, 1.60731881],
[ 0.23361565, 1.38772715, 0.69129479, -1.19228023],
[ 0.51353082, 0.17696698, -0.06753478, 0.80448168],
[ 0.21773096, 0.60582802, -0.46446071, 0.83131122],
[ 0.50569072, 0.04431685, -0.69358155, -0.9629124 ]])
data[data < 0] = 0
data
Out[75]:
array([[ 0.36762706, 0. , 0.84316735, 0. ],
[ 1.34023966, 1.12766186, 1.12507441, 0. ],
[ 1.27392366, 0. , 0. , 1.60731881],
[ 0.23361565, 1.38772715, 0.69129479, 0. ],
[ 0.51353082, 0.17696698, 0. , 0.80448168],
[ 0.21773096, 0.60582802, 0. , 0.83131122],
[ 0.50569072, 0.04431685, 0. , 0. ]])
上面展示通过布尔值来设置值的手段。
数组文件输入输出
在跑实验时常常须要用到读取文件里的数据,事实上在numpy中已经有成熟函数封装好了能够使用
将数组以二进制形式格式保存到磁盘。np.save 、np.load 函数是读写磁盘的两个主要函数。默认情况下,数组以未压缩的原始二进制格式保存在扩展名为.npy的文件里
arr = np.arange(10)
np.save('some_array',arr)
np.load('some_array.npy')
Out[80]: array([0, 1, 2, 3, 4, 5, 6, 7, 8, 9])
存取文本文件:
文本中存放是聚类须要数据,直接能够方便读取到numpy array中,省去一行行读文件繁琐。
arr = np.loadtxt('dataMatrix.txt',delimiter=' ')
arr
Out[82]:
array([[ 1. , 1. , 1. , 1. , 1. ,
0.8125 ],
[ 0.52882353, 0.56271186, 0.48220588, 0.53384615, 0.61651376,
0.58285714],
[ 0. , 0. , 0. , 1. , 1. ,
1. ],
[ 1. , 0.92857143, 0.91857143, 1. , 1. ,
1. ],
[ 1. , 1. , 1. , 1. , 1. ,
1. ],
[ 0.05285714, 0.10304348, 0.068 , 0.06512821, 0.05492308,
0.05244898],
[ 0.04803279, 0.08203125, 0.05516667, 0.05517241, 0.04953488,
0.05591549],
[ 0.04803279, 0.08203125, 0.05516667, 0.05517241, 0.04953488,
0.05591549]])
np.savetxt 运行相反的操作。这两个函数在跑实验载入数据时能够提供非常多便利!。!
使用numpy.arange方法
>>> print np.arange(15)
[ 0 1 2 3 4 5 6 7 8 9 10 11 12 13 14]
>>> print type(np.arange(15))
<type 'numpy.ndarray'>
>>> print np.arange(15).reshape(3,5)
[[ 0 1 2 3 4]
[ 5 6 7 8 9]
[10 11 12 13 14]]
>>> print type(np.arange(15).reshape(3,5))
<type 'numpy.ndarray'>
使用numpy.linspace方法
比如,在从1到10中产生20个数:
>>> print np.linspace(1,10,20)
[ 1. 1.47368421 1.94736842 2.42105263 2.89473684
3.36842105 3.84210526 4.31578947 4.78947368 5.26315789
5.73684211 6.21052632 6.68421053 7.15789474 7.63157895
8.10526316 8.57894737 9.05263158 9.52631579 10. ]
使用numpy.zeros,numpy.ones。numpy.eye等方法能够构造特定的矩阵
>>> print np.zeros((3,4))
[[ 0. 0. 0. 0.]
[ 0. 0. 0. 0.]
[ 0. 0. 0. 0.]]
>>> print np.ones((3,4))
[[ 1. 1. 1. 1.]
[ 1. 1. 1. 1.]
[ 1. 1. 1. 1.]]
>>> print np.eye(3)
[[ 1. 0. 0.]
[ 0. 1. 0.]
[ 0. 0. 1.]]
获取数组的属性:
>>> a = np.zeros((2,2,2))
>>> print a.ndim #数组的维数
3
>>> print a.shape #数组每一维的大小
(2, 2, 2)
>>> print a.size #数组的元素数
8
>>> print a.dtype #元素类型
float64
>>> print a.itemsize #每一个元素所占的字节数
8
Memory layout
The following attributes contain information about the memory layout of the array:
ndarray.flags | Information about the memory layout of the array. |
ndarray.shape | Tuple of array dimensions. |
ndarray.strides | Tuple of bytes to step in each dimension when traversing an array. |
ndarray.ndim | Number of array dimensions. |
ndarray.data | Python buffer object pointing to the start of the array’s data. |
ndarray.size | Number of elements in the array. |
ndarray.itemsize | Length of one array element in bytes. |
ndarray.nbytes | Total bytes consumed by the elements of the array. |
ndarray.base | Base object if memory is from some other object. |
Array methods
An ndarray object has many methods which operate on or with the array in some fashion, typically returning an array result. These methods are briefly explained below. (Each method’s docstring has a more complete description.)
For the following methods there are also corresponding functions in numpy: all, any, argmax, argmin, argpartition, argsort, choose, clip,compress, copy, cumprod, cumsum, diagonal, imag, max, mean, min, nonzero, partition, prod, ptp, put, ravel, real, repeat, reshape, round,searchsorted, sort, squeeze, std, sum, swapaxes, take, trace, transpose, var.
很多其它Array的相关方法见:http://docs.scipy.org/doc/numpy/reference/arrays.ndarray.html
用到比較多函数演示样例:
>>> x
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]]])
>>> x.sum(axis=1)
array([[ 9, 12, 15],
[36, 39, 42],
[63, 66, 69]])
>>> x.sum(axis=2)
array([[ 3, 12, 21],
[30, 39, 48],
[57, 66, 75]])
>>> 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下的vstack(垂直方向)和hstack(水平方向)函数:
>>> a = np.ones((2,2))
>>> b = np.eye(2)
>>> print np.vstack((a,b))
[[ 1. 1.]
[ 1. 1.]
[ 1. 0.]
[ 0. 1.]]
>>> print np.hstack((a,b))
[[ 1. 1. 1. 0.]
[ 1. 1. 0. 1.]]
看一下这两个函数有没有涉及到浅拷贝这样的问题:
>>> c = np.hstack((a,b))
>>> print c
[[ 1. 1. 1. 0.]
[ 1. 1. 0. 1.]]
>>> a[1,1] = 5
>>> b[1,1] = 5
>>> print c
[[ 1. 1. 1. 0.]
[ 1. 1. 0. 1.]]
通过上面能够知道,这里进行是深拷贝。而不是引用指向同一位置的浅拷贝。
深拷贝数组
数组对象自带了浅拷贝和深拷贝的方法,可是一般用深拷贝多一些:
>>> a = np.ones((2,2))
>>> b = a
>>> b is a
True
>>> c = a.copy() #深拷贝
>>> c is a
False
主要的矩阵运算
转置:
>>> a = np.array([[1,0],[2,3]])
>>> print a
[[1 0]
[2 3]]
>>> print a.transpose()
[[1 2]
[0 3]]
numpy.linalg模块中有非常多关于矩阵运算的方法:
特征值、特征向量:
>>> a = np.array([[1,0],[2,3]])
>>> nplg.eig(a)
(array([ 3., 1.]), array([[ 0. , 0.70710678],
[ 1. , -0.70710678]]))