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]]))