python--numpy学习(一)

NumPy 部分功能如下:

  • ndarray,一个具有矢量运算符和复杂广播能力的快速节省空间的多维数组
  • 用于对数组数据进行快速运算的标准数学函数
  • 用于读写磁盘数据的工具以及用于操作内存映射文件的工具
  • 线性代数丶随机数生成以及傅里叶变换功能
  • 用于继承由C丶C++ 丶Fortran等语言编写的代码的工具

NumPy 最重要的一个特点就是其N维数组对象(ndarray),该对象是一个快速而灵活的大数据集容器 。可以利用这个数组对象对整块数据进行一些数学运算,其语法跟标量之间的运算一样。

统一进入方式:ipython --pylab

> ipython --pylab
Python 3.6.5 (v3.6.5:f59c0932b4, Mar 28 2018, 17:00:18) [MSC v.1900 64 bit (AMD64)]
Type 'copyright', 'credits' or 'license' for more information
IPython 6.4.0 -- An enhanced Interactive Python. Type '?' for help.
Using matplotlib backend: TkAgg
In [5]: import numpy as np
In [6]: data=np.array([[0.9526,-0.246,-0.8856],[0.5639,0.2379,0.9104]])

In [7]: data
Out[7]:
array([[ 0.9526, -0.246 , -0.8856],
       [ 0.5639,  0.2379,  0.9104]])

In [8]: data * 10
Out[8]:
array([[ 9.526, -2.46 , -8.856],
       [ 5.639,  2.379,  9.104]])

In [9]: data + data
Out[9]:
array([[ 1.9052, -0.492 , -1.7712],
       [ 1.1278,  0.4758,  1.8208]])

ndarray是一个通用的同构数据多维容器,也就是说,其中的所有元素必须是相同类型的。每个数组都有一个shape(一个表示个维度大小的元组)和一个dtype(一个用于说明数组数据类型的对象)

In [29]: test_data=np.array([[1,2,3],[4,5,6],[7,8,9]])

In [30]: data
Out[30]:
array([[ 0.9526, -0.246 , -0.8856],
       [ 0.5639,  0.2379,  0.9104]])

In [31]: test_data
Out[31]:
array([[1, 2, 3],
       [4, 5, 6],
       [7, 8, 9]])

In [32]: data.shape
Out[32]: (2, 3)     #表示2行3列

In [33]: test_data.shape
Out[33]: (3, 3)    #表示3行3列
In [34]: data.dtype
Out[34]: dtype('float64')

In [35]: test_data.dtype
Out[35]: dtype('int32')

创建ndarry

创建数组最简单的办法就是使用array函数。它接受一切序列型的对象(包括其他数组),然后产生一个新的传入数据的NumPy数组。

In [1]: import numpy as np

In [2]: data1=[6,7.5,8,0,1]

In [3]: arr1=np.array(data1)

In [4]: arr1
Out[4]: array([6. , 7.5, 8. , 0. , 1. ])

因为里面有7.5为浮点数,所以:

In [5]: arr1.dtype
Out[5]: dtype('float64')

查询出的数据类型为float64

除非显示说明,np.array会尝试为新建的这个数组推断出一个较为合适的数据类型。数据类型保存在一个特殊的dtype对象中。

嵌套序列

比如一组等长的列表组成的列表,将会转换成一个多维数组 :

In [6]: data2=[[1,2,3,4],[3,4,5,6],[5,6,7,8]]

In [7]: arr2=np.array(data2)

In [8]: arr2
Out[8]:
array([[1, 2, 3, 4],
       [3, 4, 5, 6],
       [5, 6, 7, 8]])

In [9]: arr2.ndim
Out[9]: 2

In [10]: arr2.shape
Out[10]: (3, 4)

In [11]: arr2.dtype
Out[11]: dtype('int32')

其中ndim和shape介绍:

ndim:数组的维数。如二维可以通过array[x][y]获取,三维是通过array[x][y][z]获取

shape:返回值是一个元组,里面每个数字表示每一维的长度。

In [13]: arr3=np.ones([2,3,4])

In [14]: arr3
Out[14]:
array([[[1., 1., 1., 1.],
        [1., 1., 1., 1.],
        [1., 1., 1., 1.]],

       [[1., 1., 1., 1.],
        [1., 1., 1., 1.],
        [1., 1., 1., 1.]]])

In [15]: arr3.ndim
Out[15]: 3

In [16]: arr3.shape
Out[16]: (2, 3, 4)

除了np.array之外,还有一些函数可以新建数组。比如zeros和ones分别可以创建制定长度或形状的全0或全1数组。emtpy可以创建一个没有任何具体值的数组。

In [17]: np.zeros(10)
Out[17]: array([0., 0., 0., 0., 0., 0., 0., 0., 0., 0.])

In [19]: np.zeros((3,6))
Out[19]:
array([[0., 0., 0., 0., 0., 0.],
       [0., 0., 0., 0., 0., 0.],
       [0., 0., 0., 0., 0., 0.]])

In [20]: np.zeros((3,6,7))
Out[20]:
array([[[0., 0., 0., 0., 0., 0., 0.],
        [0., 0., 0., 0., 0., 0., 0.],
        [0., 0., 0., 0., 0., 0., 0.],
        [0., 0., 0., 0., 0., 0., 0.],
        [0., 0., 0., 0., 0., 0., 0.],
        [0., 0., 0., 0., 0., 0., 0.]],

       [[0., 0., 0., 0., 0., 0., 0.],
        [0., 0., 0., 0., 0., 0., 0.],
        [0., 0., 0., 0., 0., 0., 0.],
        [0., 0., 0., 0., 0., 0., 0.],
        [0., 0., 0., 0., 0., 0., 0.],
        [0., 0., 0., 0., 0., 0., 0.]],

       [[0., 0., 0., 0., 0., 0., 0.],
        [0., 0., 0., 0., 0., 0., 0.],
        [0., 0., 0., 0., 0., 0., 0.],
        [0., 0., 0., 0., 0., 0., 0.],
        [0., 0., 0., 0., 0., 0., 0.],
        [0., 0., 0., 0., 0., 0., 0.]]])

In [21]: np.ones((2,3))
Out[21]:
array([[1., 1., 1.],
       [1., 1., 1.]])

In [22]: np.ones(5)
Out[22]: array([1., 1., 1., 1., 1.])

In [27]: np.empty((2,3,1))
Out[27]:
array([[[1.],
        [1.],
        [1.]],

       [[1.],
        [1.],
        [1.]]])

In [28]: np.empty((2,3,2))
Out[28]:
array([[[0., 0.],
        [0., 0.],
        [0., 0.]],

       [[0., 0.],
        [0., 0.],
        [0., 0.]]])
View Code

注意:np.empty返回的是一些未初始化的垃圾值,并不一定返回全0数组 。

arange是python内置函数range的数组版:

In [31]: np.arange(10)
Out[31]: array([0, 1, 2, 3, 4, 5, 6, 7, 8, 9])

数组函数创建:

array:  将输入数据(列表,元组,数组或其他序列类型)转换为ndarry。 要么推断出dtype,要么显示制定dtype。默认直接复制输入数据

asarray:将输入转换成ndarry,如果本身就是一个ndarry就不进行复制。

arange:类似内置的range,但返回的是一个ndarry而不是列表。

ones 丶ones_like:根据指定的形状和dtype创建一个全1数组。ones_like 以另一个数组为参数,并根据其形状和dtype创建一个全1数组 。

zeros丶zeros_like:类似ones 丶ones_like,不过创建的是全0数组。

empty丶empty_like :创建新数组,只分配内存空间但不填充任何值

eye丶identity :创建一个N  * N 单位矩阵(对角线为1,其余为0)

In [42]: np.eye(5)
Out[42]:
array([[1., 0., 0., 0., 0.],
       [0., 1., 0., 0., 0.],
       [0., 0., 1., 0., 0.],
       [0., 0., 0., 1., 0.],
       [0., 0., 0., 0., 1.]])

In [43]: np.identity(5)
Out[43]:
array([[1., 0., 0., 0., 0.],
       [0., 1., 0., 0., 0.],
       [0., 0., 1., 0., 0.],
       [0., 0., 0., 1., 0.],
       [0., 0., 0., 0., 1.]])

ndarry的数据类型

dtype(数据类型)是一个特殊的对象,它包含有ndarry将一块内存解释为特定数据类型所需的信息:

In [45]: arr1=np.array([1,2,3],dtype=np.float64)

In [46]: arr1
Out[46]: array([1., 2., 3.])

In [47]: arr2=np.array([1,2,3],dtype=np.int32)

In [48]: arr1.dtype
Out[48]: dtype('float64')

In [49]: arr2.dtype
Out[49]: dtype('int32')

一个数组创建后,系统会自动地将python类型映射到等价的dtype上 。

可以通过ndarry的astype方法显式的转换dtype:( astype --> as type 修改类型; dtype--> 的type,查询出当前类型 )

In [51]: arr=np.array([1,2,3,4,5])

In [52]: arr.dtype
Out[52]: dtype('int32')

In [53]: float_arr=arr.astype(np.float64)

In [54]: float_arr.dtype
Out[54]: dtype('float64')

上面将整数转换成了浮点数,如果将浮点数转换成整数,那么小数部分将会截断 :

In [56]: arr=np.array([1.2,3.6,5.3,4.8,7.0,5.11,8.12])

In [57]: arr
Out[57]: array([1.2 , 3.6 , 5.3 , 4.8 , 7.  , 5.11, 8.12])

In [58]: arr.astype(np.int32)
Out[58]: array([1, 3, 5, 4, 7, 5, 8])

还有另外一个用法:

In [65]: float_array
Out[65]: array([1.2 , 5.8 , 2.89, 7.53])

In [66]: int_array
Out[66]: array([0, 1, 2, 3, 4, 5, 6, 7, 8, 9])

In [67]: float_array.dtype
Out[67]: dtype('float64')

In [68]: int_array.dtype
Out[68]: dtype('int32')

In [69]: int_array.astype(float_array.dtype)
Out[69]: array([0., 1., 2., 3., 4., 5., 6., 7., 8., 9.])

In [70]: int_array.dtype
Out[70]: dtype('int32')

In [71]: int_arr=int_array.astype(float_array.dtype)

In [72]: int_arr.dtype
Out[72]: dtype('float64')

从上面可以看到int_array原始数据类型为int32,float_array为float64,执行int_array.astype(float_array.dtype)后是将int_array数据类型设置为float_array的一样,但是70行再次查询时发现int_array数据类型仍然是int32,只有定义一个新数组来接受时,新数组类型才是float64

总结:astype使用方法ndarry.astype(np.dtype) 返回一个新的,dtype为传入的新的dtype的新数组,原始数组数据类型保持不变 。

数组和标量之间的运算

大小相等的数组之间的任何算术运算都会将运算应用到元素级:

In [89]: arr1
Out[89]:
array([[1, 2, 3],
       [4, 5, 6]])

In [90]: arr2
Out[90]:
array([[1, 2, 3],
       [4, 5, 2]])

In [91]: arr1 * arr2
Out[91]:
array([[ 1,  4,  9],
       [16, 25, 12]])

In [92]: arr1 + arr2
Out[92]:
array([[ 2,  4,  6],
       [ 8, 10,  8]])

In [93]: arr1 ** 2
Out[93]:
array([[ 1,  4,  9],
       [16, 25, 36]], dtype=int32)

In [94]: 1 / arr1
Out[94]:
array([[1.        , 0.5       , 0.33333333],
       [0.25      , 0.2       , 0.16666667]])

不同大小的数组之间的运算叫做广播。

 基本的索引和切片

In [1]: arr=np.arange(10)

In [2]: arr
Out[2]: array([0, 1, 2, 3, 4, 5, 6, 7, 8, 9])

In [3]: arr[5:8]
Out[3]: array([5, 6, 7])

In [4]: arr[5:8]=12

In [5]: arr
Out[5]: array([ 0,  1,  2,  3,  4, 12, 12, 12,  8,  9])

In [6]: arr_slice=arr[5:8]

In [7]: arr_slice
Out[7]: array([12, 12, 12])

In [8]: arr_slice[1]
Out[8]: 12

In [9]: arr_slice[1]=12345

In [10]: arr
Out[10]:
array([    0,     1,     2,     3,     4,    12, 12345,    12,     8,
           9])

In [11]: arr_slice[:]=64

In [12]: arr
Out[12]: array([ 0,  1,  2,  3,  4, 64, 64, 64,  8,  9])

可以发现,当你将一个标量值赋值给一个切片时(如arr[5:8]=12) ,该值会自动传播到整个选区。跟列表最重要的区别在于,数组切片是原始数组的视图。这意味着数据不会被复制,视图上的任何修改都会直接反映到源数组上。

对于高维度数组,能做的事情更多。在一个二维数组中,各索引位置上的元素不再是标量而是一维数组。

In [13]: arr2d=np.array([[1,2,3],[4,5,6],[7,8,9]])

In [14]: arr2d[2]
Out[14]: array([7, 8, 9])    #第三个数组

In [15]: arr2d[0][2]       #第一个数组的第三个
Out[15]: 3

在多维数组中,如果省略了后面的索引,则返回对象是一个维度低一点的ndarry 。

比如,在下面的一个2 * 2 * 3的数组arr3d中:

In [16]: arr3d=np.array([[[1,2,3],[4,5,6]],[[7,8,9],[10,11,12]]])

In [17]: arr3d
Out[17]:
array([[[ 1,  2,  3],
        [ 4,  5,  6]],

       [[ 7,  8,  9],
        [10, 11, 12]]])

In [18]: arr3d[0]  #先去掉最外面的[],然后取第一个列表 
Out[18]:
array([[1, 2, 3],
       [4, 5, 6]])

In [19]: arr3d[0][1]   #从最外面的[]看起,先取第一个列表,再从里面取第二个 
Out[19]: array([4, 5, 6])

标量和数组都可以赋值给arr3d[0]

In [20]: old_values=arr3d[0].copy()   #先将arr3d[0]的值赋给old_values

Out[22]:
array([[1, 2, 3],
       [4, 5, 6]])

In [23]: arr3d[0]=42   #修改值后

In [24]: arr3d
Out[24]:
array([[[42, 42, 42],
        [42, 42, 42]],

       [[ 7,  8,  9],
        [10, 11, 12]]])

In [25]: arr3d[0]=old_values   #重新赋值

In [26]: arr3d
Out[26]:
array([[[ 1,  2,  3],
        [ 4,  5,  6]],

       [[ 7,  8,  9],
        [10, 11, 12]]])

切片索引

ndarry的切片语法跟python列表这样的一维对象差不多:

In [1]: arr=np.array([0,1,2,3,4,64,64,64,8,9])

In [2]: arr[1:6]
Out[2]: array([ 1,  2,  3,  4, 64])

高维度对象的花样更多,可以在一个或多个轴上进行切片,也可以跟整数索引混合使用。

In [4]: arr2d
Out[4]:
array([[1, 2, 3],
       [4, 5, 6],
       [7, 8, 9]])

In [5: arr2d[:2]   #取第一个(下标为0)和第二个(下标为1)
Out[5]:
array([[1, 2, 3],
       [4, 5, 6]])

可以一次传入多个切片,就像传入多个索引一样:

In [8]: arr2d[:2,:1]
Out[8]:
array([[1],
       [4]])

通过整数索引和切片混合,可以得到低维度的切片:

In [9]: arr2d[1,:2]
Out[9]: array([4, 5])  #先取下标1的,即第二个列表,然后切片[:2]取前2个

In [10]: arr2d
Out[10]:
array([[1, 2, 3],
       [4, 5, 6],
       [7, 8, 9]])

切片跟切片混合的,只能得到相同维数的数组视图。但是数组索引跟切片混合可以得到低维度的数组视图。数组索引跟数组索引混合,得到的是低维度的视图或数值:

下面介绍数组索引和数组索引混合:

In [19]: arr3d   #原始数组
Out[19]:
array([[[ 1,  2,  3],
        [ 4,  5,  6]],

       [[ 7,  8,  9],
        [10, 11, 12]]])

In [21]: arr3d[1]   #取第二个数组
Out[21]:             #得到一个二维数组
array([[ 7,  8,  9],
       [10, 11, 12]])

In [22]: arr3d[1,1]    #取第二个数组,然后再取第二个
Out[22]: array([10, 11, 12])   #得到一个一维数组

In [24]: arr3d[1,1,1]  #取第二个数组,然后再取第二个,然后再取第二个
Out[24]: 11   #得到一个数值
原文地址:https://www.cnblogs.com/catxjd/p/9058324.html