python numpy 基础教程

很简单,Numpy是Python的一个科学计算的库,提供了矩阵运算的功能,其一般与Scipy、matplotlib一起使用。其实,list已经提供了类似于矩阵的表示形式,不过numpy为我们提供了更多的函数。如果接触过matlab、scilab,那么numpy很好入手。 在以下的代码示例中,总是先导入了numpy:(通用做法import numpu as np 简单输入)

 

以list或tuple变量为元素产生二维数组或者多维数组:

[python] 
view plain
 copy  

  1. >>> x = np.array(((1,2,3),(4,5,6)))  
  2. >>> x  
  3. array([[1, 2, 3],  
  4.        [4, 5, 6]])  
  5. >>> y = np.array([[1,2,3],[4,5,6]])  
  6. >>> y  
  7. array([[1, 2, 3],  
  8.        [4, 5, 6]])  

涉及改变相关问题,我们改变上面y是否会改变x?这是特别需要关注的!

[python] 
view plain
 copy  

  1. >>> y  
  2. array([2, 5])  
  3. >>> y[0] = 10  
  4. >>> y  
  5. array([10,  5])  
  6. >>> x  
  7. array([[ 1, 10,  3],  
  8.        [ 4,  5,  6]])  

通过上面可以发现改变y会改变x ,因而我们可以推断,y和x指向是同一块内存空间值,系统没有为y 新开辟空间把x值赋值过去。

 

[python] 
view plain
 copy  

  1. arr = np.arange(10)  
  2.   
  3. arr  
  4. Out[45]: array([0, 1, 2, 3, 4, 5, 6, 7, 8, 9])  
  5.   
  6. arr[4]  
  7. Out[46]: 4  
  8.   
  9. arr[3:6]  
  10. Out[47]: array([3, 4, 5])  
  11.   
  12. arr[3:6] = 12  
  13.   
  14. arr  
  15. Out[49]: array([ 0,  1,  2, 12, 12, 12,  6,  7,  8,  9])  

如上所示:当将一个标量赋值给切片时,该值会自动传播整个切片区域,这个跟列表最重要本质区别,数组切片是原始数组的视图,视图上任何修改直接反映到源数据上面。

 

思考为什么这么设计? Numpy 设计是为了处理大数据,如果切片采用数据复制话会产生极大的性能和内存消耗问题。

假如说需要对数组是一份副本而不是视图可以如下操作:

 

[python] 
view plain
 copy  

  1. arr_copy = arr[3:6].copy()  
  2. arr_copy[:]=24  
  3. arr_copy  
  4. Out[54]: array([24, 24, 24])  
  5. arr  
  6. Out[55]: array([ 0,  1,  2, 12, 12, 12,  6,  7,  8,  9])  

再看下对list 切片修改

 

[python] 
view plain
 copy  

  1. l=range(10)  
  2. l  
  3. Out[35]: [0, 1, 2, 3, 4, 5, 6, 7, 8, 9]  
  4. l[5:8] = 12  
  5. Traceback (most recent call last):  
  6.   File “<ipython-input-36-022af3ddcc9b>”, line 1, in <module>  
  7.     l[5:8] = 12  
  8. TypeError: can only assign an iterable  
  9. l1= l[5:8]  
  10. l1  
  11. Out[38]: [5, 6, 7]  
  12. l1[0]=12  
  13. l1  
  14. Out[40]: [12, 6, 7]  
  15. l  
  16. Out[41]: [0, 1, 2, 3, 4, 5, 6, 7, 8, 9]  

这里设计到python 中深浅拷贝,其中切片属于浅拷贝,具体参考:python深浅拷贝

 

多维数组索引、切片

 

[python] 
view plain
 copy  

  1. arr2d = np.arange(1,10).reshape(3,3)  
  2.   
  3. arr2d  
  4. Out[57]:   
  5. array([[1, 2, 3],  
  6.        [4, 5, 6],  
  7.        [7, 8, 9]])  
  8.   
  9. arr2d[2]  
  10. Out[58]: array([7, 8, 9])  
  11.   
  12. arr2d[0][2]  
  13. Out[59]: 3  
  14.   
  15. arr2d[0,2]  
  16. Out[60]: 3  


布尔型索引

 

这种类型在实际代码中出现比较多,关注下。

 

[python] 
view plain
 copy  

  1. names = np.array([‘Bob’,‘joe’,‘Bob’,‘will’])  
  2.   
  3. names == ‘Bob’  
  4. Out[70]: array([ True, False,  True, False], dtype=bool)  


[python] 
view plain
 copy  

  1. data  
  2. Out[73]:   
  3. array([[ 0.36762706, –1.55668952,  0.84316735, –0.116842  ],  
  4.        [ 1.34023966,  1.12766186,  1.12507441, –0.68689309],  
  5.        [ 1.27392366, –0.43399617, –0.80444728,  1.60731881],  
  6.        [ 0.23361565,  1.38772715,  0.69129479, –1.19228023],  
  7.        [ 0.51353082,  0.17696698, –0.06753478,  0.80448168],  
  8.        [ 0.21773096,  0.60582802, –0.46446071,  0.83131122],  
  9.        [ 0.50569072,  0.04431685, –0.69358155, –0.9629124 ]])  
  10.   
  11. data[data < 0] = 0  
  12.   
  13. data  
  14. Out[75]:   
  15. array([[ 0.36762706,  0.        ,  0.84316735,  0.        ],  
  16.        [ 1.34023966,  1.12766186,  1.12507441,  0.        ],  
  17.        [ 1.27392366,  0.        ,  0.        ,  1.60731881],  
  18.        [ 0.23361565,  1.38772715,  0.69129479,  0.        ],  
  19.        [ 0.51353082,  0.17696698,  0.        ,  0.80448168],  
  20.        [ 0.21773096,  0.60582802,  0.        ,  0.83131122],  
  21.        [ 0.50569072,  0.04431685,  0.        ,  0.        ]])  


上面展示通过布尔值来设置值的手段。

数组文件输入输出

在跑实验时经常需要用到读取文件中的数据,其实在numpy中已经有成熟函数封装好了可以使用

将数组以二进制形式格式保存到磁盘,np.save 、np.load 函数是读写磁盘的两个主要函数,默认情况下,数组以未压缩的原始二进制格式保存在扩展名为.npy的文件中

 

[python] 
view plain
 copy  

  1. arr = np.arange(10)  
  2. np.save(‘some_array’,arr)  


[python] 
view plain
 copy  

  1. np.load(‘some_array.npy’)  
  2. Out[80]: array([0, 1, 2, 3, 4, 5, 6, 7, 8, 9])  

存取文本文件:

 

文本中存放是聚类需要数据,直接可以方便读取到numpy array中,省去一行行读文件繁琐。

 

[python] 
view plain
 copy  

  1. arr = np.loadtxt(‘dataMatrix.txt’,delimiter=‘ ‘)  
  2.   
  3. arr  
  4. Out[82]:   
  5. array([[ 1.        ,  1.        ,  1.        ,  1.        ,  1.        ,  
  6.          0.8125    ],  
  7.        [ 0.52882353,  0.56271186,  0.48220588,  0.53384615,  0.61651376,  
  8.          0.58285714],  
  9.        [ 0.        ,  0.        ,  0.        ,  1.        ,  1.        ,  
  10.          1.        ],  
  11.        [ 1.        ,  0.92857143,  0.91857143,  1.        ,  1.        ,  
  12.          1.        ],  
  13.        [ 1.        ,  1.        ,  1.        ,  1.        ,  1.        ,  
  14.          1.        ],  
  15.        [ 0.05285714,  0.10304348,  0.068     ,  0.06512821,  0.05492308,  
  16.          0.05244898],  
  17.        [ 0.04803279,  0.08203125,  0.05516667,  0.05517241,  0.04953488,  
  18.          0.05591549],  
  19.        [ 0.04803279,  0.08203125,  0.05516667,  0.05517241,  0.04953488,  
  20.          0.05591549]])  


np.savetxt 执行相反的操作,这两个函数在跑实验加载数据时可以提供很多便利!!!

 

使用numpy.arange方法

[python] 
view plain
 copy  

  1. >>> print np.arange(15)  
  2. 0  1  2  3  4  5  6  7  8  10 11 12 13 14]  
  3. >>> print type(np.arange(15))  
  4. <type ‘numpy.ndarray’>  
  5. >>> print np.arange(15).reshape(3,5)  
  6. [[ 0  1  2  3  4]  
  7.  [ 5  6  7  8  9]  
  8.  [10 11 12 13 14]]  
  9. >>> print type(np.arange(15).reshape(3,5))  
  10. <type ‘numpy.ndarray’>  

使用numpy.linspace方法

 

例如,在从1到10中产生20个数:

[python] 
view plain
 copy  

  1. >>> print np.linspace(1,10,20)  
  2. [  1.           1.47368421   1.94736842   2.42105263   2.89473684  
  3.    3.36842105   3.84210526   4.31578947   4.78947368   5.26315789  
  4.    5.73684211   6.21052632   6.68421053   7.15789474   7.63157895  
  5.    8.10526316   8.57894737   9.05263158   9.52631579  10.        ]  

使用numpy.zeros,numpy.ones,numpy.eye等方法可以构造特定的矩阵

[python] 
view plain
 copy  

  1. >>> print np.zeros((3,4))  
  2. [[ 0.  0.  0.  0.]  
  3.  [ 0.  0.  0.  0.]  
  4.  [ 0.  0.  0.  0.]]  
  5. >>> print np.ones((3,4))  
  6. [[ 1.  1.  1.  1.]  
  7.  [ 1.  1.  1.  1.]  
  8.  [ 1.  1.  1.  1.]]  
  9. >>> print np.eye(3)  
  10. [[ 1.  0.  0.]  
  11.  [ 0.  1.  0.]  
  12.  [ 0.  0.  1.]]  

获取数组的属性:

[python] 
view plain
 copy  

  1. >>> a = np.zeros((2,2,2))  
  2. >>> print a.ndim   #数组的维数  
  3. 3  
  4. >>> print a.shape  #数组每一维的大小  
  5. (2, 2, 2)  
  6. >>> print a.size   #数组的元素数  
  7. 8  
  8. >>> print a.dtype  #元素类型  
  9. float64  
  10. >>> print a.itemsize  #每个元素所占的字节数  
  11. 8  

Memory layout

The following attributes contain information about the memory layout of the array:

 

ndarray.flagsInformation about the memory layout of the array.
ndarray.shapeTuple of array dimensions.
ndarray.stridesTuple of bytes to step in each dimension when traversing an array.
ndarray.ndimNumber of array dimensions.
ndarray.dataPython buffer object pointing to the start of the array’s data.
ndarray.sizeNumber of elements in the array.
ndarray.itemsizeLength of one array element in bytes.
ndarray.nbytesTotal bytes consumed by the elements of the array.
ndarray.baseBase 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 numpyallanyargmaxargminargpartitionargsortchooseclip,compresscopycumprodcumsumdiagonalimagmaxmeanminnonzeropartitionprodptpputravelrealrepeatreshaperound,searchsortedsortsqueezestdsumswapaxestaketracetransposevar.

更多Array的相关方法见:http://docs.scipy.org/doc/numpy/reference/arrays.ndarray.html

用到比较多函数示例:

[python] 
view plain
 copy  

  1. >>> x  
  2. array([[[ 0,  1,  2],  
  3.         [ 3,  4,  5],  
  4.         [ 6,  7,  8]],  
  5.   
  6.        [[ 9, 10, 11],  
  7.         [12, 13, 14],  
  8.         [15, 16, 17]],  
  9.   
  10.        [[18, 19, 20],  
  11.         [21, 22, 23],  
  12.         [24, 25, 26]]])  
  13. >>> x.sum(axis=1)  
  14. array([[ 9, 12, 15],  
  15.        [36, 39, 42],  
  16.        [63, 66, 69]])  
  17. >>> x.sum(axis=2)  
  18. array([[ 3, 12, 21],  
  19.        [30, 39, 48],  
  20.        [57, 66, 75]])  

[python] 
view plain
 copy  

  1. >>> np.sum([[0, 1], [0, 5]])  
  2. 6  
  3. >>> np.sum([[0, 1], [0, 5]], axis=0)  
  4. array([0, 6])  
  5. >>> np.sum([[0, 1], [0, 5]], axis=1)  
  6. array([1, 5])  

合并数组

使用numpy下的vstack(垂直方向)和hstack(水平方向)函数:

[python] 
view plain
 copy  

  1. >>> a = np.ones((2,2))  
  2. >>> b = np.eye(2)  
  3. >>> print np.vstack((a,b))  
  4. [[ 1.  1.]  
  5.  [ 1.  1.]  
  6.  [ 1.  0.]  
  7.  [ 0.  1.]]  
  8. >>> print np.hstack((a,b))  
  9. [[ 1.  1.  1.  0.]  
  10.  [ 1.  1.  0.  1.]]  

 

看一下这两个函数有没有涉及到浅拷贝这种问题:

[python] 
view plain
 copy  

  1. >>> c = np.hstack((a,b))  
  2. >>> print c  
  3. [[ 1.  1.  1.  0.]  
  4.  [ 1.  1.  0.  1.]]  
  5. >>> a[1,1] = 5  
  6. >>> b[1,1] = 5  
  7. >>> print c  
  8. [[ 1.  1.  1.  0.]  
  9.  [ 1.  1.  0.  1.]]  

通过上面可以知道,这里进行是深拷贝,而不是引用指向同一位置的浅拷贝。

深拷贝数组

数组对象自带了浅拷贝和深拷贝的方法,但是一般用深拷贝多一些:

[python] 
view plain
 copy  

  1. >>> a = np.ones((2,2))  
  2. >>> b = a  
  3. >>> b is a  
  4. True  
  5. >>> c = a.copy()  #深拷贝  
  6. >>> c is a  
  7. False  

 

基本的矩阵运算

转置:

[python] 
view plain
 copy  

  1. >>> a = np.array([[1,0],[2,3]])  
  2. >>> print a  
  3. [[0]  
  4.  [3]]  
  5. >>> print a.transpose()  
  6. [[2]  
  7.  [3]]  

numpy.linalg模块中有很多关于矩阵运算的方法:

特征值、特征向量:

[python] 
view plain
 copy  

  1. >>> a = np.array([[1,0],[2,3]])  
  2.   
  3. >>> nplg.eig(a)  
  4. (array([ 3.,  1.]), array([[ 0.        ,  0.70710678],  
  5.        [ 1.        , –0.70710678]]))  

 

     

点赞