美文网首页Python之旅Python我爱编程
numpy基础——ndarray对象

numpy基础——ndarray对象

作者: happy_19 | 来源:发表于2016-09-11 22:41 被阅读14358次

    numpy 是使用python进行数据分析不可或缺的第三方库,非常多的科学计算工具都是基于 numpy 进行开发的。

    ndarray对象是用于存放同类型元素的多维数组,是numpy中的基本对象之一,另一个是func对象。本文主要内容是:1 、简单介绍ndarray对象2、ndarray对象的常用属性3、如何创建ndarray对象4、ndarray元素访问
    它的维度以及个维度上的元素个数由shape决定。

    1 numpy.ndarray()

    标题中的函数就是numpy的构造函数,我们可以使用这个函数创建一个ndarray对象。构造函数有如下几个可选参数:

    参数 类型 作用
    shape int型tuple 多维数组的形状
    dtype data-type 数组中元素的类型
    buffer 用于初始化数组的buffer
    offset int buffer中用于初始化数组的首个数据的偏移
    strides int型tuple 每个轴的下标增加1时,数据指针在内存中增加的字节数
    order 'C' 或者 'F' 'C':行优先;'F':列优先

    实例:

    >>> np.ndarray(shape=(2,3), dtype=int, buffer=np.array([1,2,3,4,5,6,7]), offset=0, order="C") 
    array([[1, 2, 3],
           [4, 5, 6]])
    >>> np.ndarray(shape=(2,3), dtype=int, buffer=np.array([1,2,3,4,5,6,7]), offset=0, order="F")
    array([[1, 3, 5],
           [2, 4, 6]])
    >>> np.ndarray(shape=(2,3), dtype=int, buffer=np.array([1,2,3,4,5,6,7]), offset=8, order="C") 
    array([[2, 3, 4],
           [5, 6, 7]])
    

    2 ndarray对象的常用属性

    接下来介绍ndarray对象最常用的属性

    属性 含义
    T 转置,与self.transpose( )相同,如果维度小于2返回self
    size 数组中元素个数
    itemsize 数组中单个元素的字节长度
    dtype 数组元素的数据类型对象
    ndim 数组的维度
    shape 数组的形状
    data 指向存放数组数据的python buffer对象
    flat 返回数组的一维迭代器
    imag 返回数组的虚部
    real 返回数组的实部
    nbytes 数组中所有元素的字节长度

    实例:

    >>> a = np.array(range(15)).reshape(3,5)
    >>> a
    array([[ 0,  1,  2,  3,  4],
           [ 5,  6,  7,  8,  9],
           [10, 11, 12, 13, 14]])
    >>> a.T
    array([[ 0,  5, 10],
           [ 1,  6, 11],
           [ 2,  7, 12],
           [ 3,  8, 13],
           [ 4,  9, 14]])
    >>> a.size
    15
    >>> a.itemsize
    8
    >>> a.ndim
    2
    >>> a.shape
    (3, 5)
    >>> a.dtype
    dtype('int64')
    

    3 创建ndarray

    3.1 array

    使用array函数,从常规的python列表或者元组中创建数组,元素的类型由原序列中的元素类型确定。

    numpy.array(object, dtype=None, copy=True, order=None, subok=False, ndmin=0)
    

    实例:

    >>> np.array([1, 2, 3])
    array([1, 2, 3])
    >>> np.array([[1, 2],[3, 4]])
    array([[1, 2],
           [3, 4]])
    >>> c = array( [ [1,2], [3,4] ], dtype=complex )
    >>> c
    array([[1.+0.j, 2.+0.j], 
           [3.+0.j, 4.+0.j]])
    >>> a = np.array([1, 2, 3], ndmin=2)
    >>> a
    array([[1, 2, 3]])
    >>> a.shape
    (1, 3)
    >>> np.array(np.mat('1 2; 3 4'))
    array([[1, 2],
           [3, 4]])
    >>> np.array(np.mat('1 2; 3 4'), subok=True)
    matrix([[1, 2],
            [3, 4]])
    

    subokTrue,并且object是ndarray子类时(比如矩阵类型),返回的数组保留子类类型

    3.2 ones与zeros系列函数

    某些时候,我们在创建数组之前已经确定了数组的维度以及各维度的长度。这时我们就可以使用numpy内建的一些函数来创建ndarray。
    例如:函数ones创建一个全1的数组、函数zeros创建一个全0的数组、函数empty创建一个内容随机的数组,在默认情况下,用这些函数创建的数组的类型都是float64,若需要指定数据类型,只需要闲置dtype参数即可:

    >>> a = np.ones(shape = (2, 3))    #可以通过元组指定数组形状
    >>> a
    array([[ 1.,  1.,  1.],
           [ 1.,  1.,  1.]])
    >>> a.dtype
    dtype('float64')
    >>> b = np.zeros(shape = [3, 2], dtype=np.int64)    #也可以通过列表来指定数组形状,同时这里指定了数组类型
    >>> b
    array([[0, 0],
           [0, 0],
           [0, 0]])
    >>> b.dtype
    dtype('int64')
    >>> c = np.empty((4,2))
    >>> c
    array([[  0.00000000e+000,   0.00000000e+000],
           [  6.92806325e-310,   6.92806326e-310],
           [  6.92806326e-310,   6.92806326e-310],
           [  0.00000000e+000,   0.00000000e+000]])
    

    上述三个函数还有三个从已知的数组中,创建shape相同的多维数组:ones_likezeros_likeempty_like,用法如下:

    >>> a = [[1,2,3], [3,4,5]]
    >>> b = np.zeros_like(a)
    >>> b
    array([[0, 0, 0],
           [0, 0, 0]])
    #其他两个函数用法类似
    

    除了上述几个用于创建数组的函数,还有如下几个特殊的函数:

    函数名 用途
    eye 生成对角线全1,其余位置全是0的二维数组
    identity 生成单位矩阵
    full 生成由固定值填充的数组
    full_like 生成由固定值填充的、形状与给定数组相同的数组

    特别地,eye函数的全1的对角线位置有参数k确定
    用法如下:

    >>> np.eye(3, k = 0)    #k=0时,全1对角线为主对角线
    array([[ 1.,  0.,  0.],
           [ 0.,  1.,  0.],
           [ 0.,  0.,  1.]])
    >>> np.eye(3, k = 1)  #k>0时,全1对角线向上移动相应的位置
    array([[ 0.,  1.,  0.],
           [ 0.,  0.,  1.],
           [ 0.,  0.,  0.]])
    >>> np.eye(3, k = -1)  #k<0时,全1对角线向下移动相应的位置
    array([[ 0.,  0.,  0.],
           [ 1.,  0.,  0.],
           [ 0.,  1.,  0.]])
    >>> np.identity(4)
    array([[ 1.,  0.,  0.,  0.],
           [ 0.,  1.,  0.,  0.],
           [ 0.,  0.,  1.,  0.],
           [ 0.,  0.,  0.,  1.]])
    >>> np.full(shape = (2,2), fill_value = 2)
    array([[ 2.,  2.],
           [ 2.,  2.]])
    >>> np.full_like([[1,2,3],[3,4,5]], 3)
    array([[3, 3, 3],
           [3, 3, 3]])
    

    3.3 arange、linspace与logspace

    1. arange函数类似python中的range函数,通过指定初始值、终值以及步长(默认步长为1)来创建数组
    2. linspace函数通过指定初始值、终值以及元素个数来创建一维数组
    3. logspace函数与linspace类似,只不过它创建的是一个等比数列,同样的也是一个一维数组
      实例:
    >>> np.arange(0,10,2) 
    array([0, 2, 4, 6, 8])
    >>> np.arange(0,10)
    array([0, 1, 2, 3, 4, 5, 6, 7, 8, 9])
    >>> np.linspace(0,10, 20)
    array([  0.        ,   0.52631579,   1.05263158,   1.57894737,
             2.10526316,   2.63157895,   3.15789474,   3.68421053,
             4.21052632,   4.73684211,   5.26315789,   5.78947368,
             6.31578947,   6.84210526,   7.36842105,   7.89473684,
             8.42105263,   8.94736842,   9.47368421,  10.        ])
    >>> np.logspace(0, 10, 10)
    array([  1.00000000e+00,   1.29154967e+01,   1.66810054e+02,
             2.15443469e+03,   2.78255940e+04,   3.59381366e+05,
             4.64158883e+06,   5.99484250e+07,   7.74263683e+08,
             1.00000000e+10])
    

    3.4 fromstring与fromfunction

    1. fromstring函数从字符串中读取数据并创建数组
    2. fromfunction函数由第一个参数作为计算每个数组元素的函数(函数对象或者lambda表达式均可),第二个参数为数组的形状
      实例:
    >>> s1 = "1,2,3,4,5"
    >>> np.fromstring(s1, dtype=np.int64, sep=",")
    array([1, 2, 3, 4, 5])
    >>> s2 = "1.01 2.23 3.53 4.76"
    >>> np.fromstring(s2, dtype=np.float64, sep=" ")
    array([ 1.01,  2.23,  3.53,  4.76])
    >>> def func(i, j):
    ...     return (i+1)*(j+1)
    ... 
    >>> np.fromfunction(func, (9,9))
    array([[  1.,   2.,   3.,   4.,   5.,   6.,   7.,   8.,   9.],
           [  2.,   4.,   6.,   8.,  10.,  12.,  14.,  16.,  18.],
           [  3.,   6.,   9.,  12.,  15.,  18.,  21.,  24.,  27.],
           [  4.,   8.,  12.,  16.,  20.,  24.,  28.,  32.,  36.],
           [  5.,  10.,  15.,  20.,  25.,  30.,  35.,  40.,  45.],
           [  6.,  12.,  18.,  24.,  30.,  36.,  42.,  48.,  54.],
           [  7.,  14.,  21.,  28.,  35.,  42.,  49.,  56.,  63.],
           [  8.,  16.,  24.,  32.,  40.,  48.,  56.,  64.,  72.],
           [  9.,  18.,  27.,  36.,  45.,  54.,  63.,  72.,  81.]])
    >>> np.fromfunction(lambda i,j: i+j, (3,3), dtype = int)
    array([[0, 1, 2],
           [1, 2, 3],
           [2, 3, 4]])
    

    除了上面两个函数还有其他几个类似的从外部获取数据并创建ndarray,比如:frombufferfromfilefromiter,还没用过,等用到了在详细记录

    4 ndarray创建特殊的二维数组

    ndarray提供了一些创建二维数组的特殊函数。numpy中matrix是对二维数组ndarray进行了封装之后的子类。这里介绍的关于二维数组的创建,返回的依旧是一个ndarray对象,而不是matrix子类。关于matrix的创建和操作,待后续笔记详细描述。为了表述方便,下面依旧使用矩阵这一次来表示创建的二维数组。

    1. diag函数返回一个矩阵的对角线元素、或者创建一个对角阵,对角线由参数k控制
    2. diagflat函数以输入作为对角线元素,创建一个矩阵,对角线由参数k控制
    3. tri函数生成一个矩阵,在某对角线以下元素全为1,其余全为0,对角线由参数k控制
    4. tril函数输入一个矩阵,返回该矩阵的下三角矩阵,下三角的边界对角线由参数k控制
    5. triu函数与tril类似,返回的是矩阵的上三角矩阵
    6. vander函数输入一个一维数组,返回一个范德蒙德矩阵
    #diag用法
    >>> x = np.arange(9).reshape((3,3))
    >>> x
    array([[0, 1, 2],
           [3, 4, 5],
           [6, 7, 8]])
    >>> np.diag(x)
    array([0, 4, 8])
    >>> np.diag(x, k=1)
    array([1, 5])
    >>> np.diag(x, k=-1)
    array([3, 7])
    >>> np.diag(np.diag(x))
    array([[0, 0, 0],
           [0, 4, 0],
           [0, 0, 8]])
    >>> np.diag(np.diag(x), k=1)
    array([[0, 0, 0, 0],
           [0, 0, 4, 0],
           [0, 0, 0, 8],
           [0, 0, 0, 0]])
    #diagflat用法
    >>> np.diagflat([[1,2],[3,4]])
    array([[1, 0, 0, 0],
           [0, 2, 0, 0],
           [0, 0, 3, 0],
           [0, 0, 0, 4]])
    >>> np.diagflat([1,2,3], k=-1)
    array([[0, 0, 0, 0],
           [1, 0, 0, 0],
           [0, 2, 0, 0],
           [0, 0, 3, 0]])
    #tri
    >>> np.tri(3,4, k=1, dtype=int)  
    array([[1, 1, 0, 0],
           [1, 1, 1, 0],
           [1, 1, 1, 1]])
    >>> np.tri(3,4)
    array([[ 1.,  0.,  0.,  0.],
           [ 1.,  1.,  0.,  0.],
           [ 1.,  1.,  1.,  0.]])
    #tril与triu
    >>> x = np.arange(12).reshape((3,4))
    >>> x
    array([[ 0,  1,  2,  3],
           [ 4,  5,  6,  7],
           [ 8,  9, 10, 11]])
    >>> np.tril(x, k=1) 
    array([[ 0,  1,  0,  0],
           [ 4,  5,  6,  0],
           [ 8,  9, 10, 11]])
    >>> np.triu(x, k=1) 
    array([[ 0,  1,  2,  3],
           [ 0,  0,  6,  7],
           [ 0,  0,  0, 11]])
    #vander
    >>> np.vander([2,3,4,5])
    array([[  8,   4,   2,   1],
           [ 27,   9,   3,   1],
           [ 64,  16,   4,   1],
           [125,  25,   5,   1]])
    >>> np.vander([2,3,4,5], N=3)
    array([[ 4,  2,  1],
           [ 9,  3,  1],
           [16,  4,  1],
           [25,  5,  1]])
    

    5 ndarray元素访问

    5.1 一维数组

    对于一维的ndarray可以使用python访问内置list的方式进行访问:整数索引、切片、迭代等方式
    关于ndarray切片
    与内置list切片类似,形式:
    array[beg:end:step]
    beg: 开始索引
    end: 结束索引(不包含这个元素)
    step: 间隔
    需要注意的是

    1. beg可以为空,表示从索引0开始;
    2. end也可以为空,表示达到索引结束(包含最后一个元素);
    3. step为空,表示间隔为1;
    4. 负值索引:倒数第一个元素的索引为-1,向前以此减1
    5. 负值step:从后往前获取元素
    >>> x = np.arange(16)*4
    >>> x
    array([ 0,  4,  8, 12, 16, 20, 24, 28, 32, 36, 40, 44, 48, 52, 56, 60])
    >>> x[11]
    44
    >>> x[4:9]
    array([16, 20, 24, 28, 32])
    >>> x[:10:3]
    array([ 0, 12, 24, 36])
    >>> x[0:13:2]
    array([ 0,  8, 16, 24, 32, 40, 48])
    >>> x[::-1]    #逆置数组
    array([60, 56, 52, 48, 44, 40, 36, 32, 28, 24, 20, 16, 12,  8,  4,  0])
    >>> print [val for val in x]    #迭代元素
    [0, 4, 8, 12, 16, 20, 24, 28, 32, 36, 40, 44, 48, 52, 56, 60]
    

    特别注意的是,ndarray中的切片返回的数组中的元素是原数组元素的索引,对返回数组元素进行修改会影响原数组的值

    >>> x[:-1]
    array([ 0,  5, 10, 15, 20, 25, 30, 35, 40])
    >>> y = x[::-1]
    >>> y
    array([45, 40, 35, 30, 25, 20, 15, 10,  5,  0])
    >>> y[0] = 100    #修改y的首个元素的值
    >>> y
    array([100,  40,  35,  30,  25,  20,  15,  10,   5,   0])
    >>> x      #x[-1]也被修改(本质上是一个元素)
    array([  0,   5,  10,  15,  20,  25,  30,  35,  40, 100])
    

    除了上述与list相似的访问元素的方式,ndarray有一种通过列表来指定要从ndarray中获取元素的索引,例如:

    >>> x = np.arange(10)*5
    >>> x
    array([ 0,  5, 10, 15, 20, 25, 30, 35, 40, 45])
    >>> x[[0, 2, 4, 5, 9]]    #指定获取索引为0、2、4、5、9的元素
    array([ 0, 10, 20, 25, 45])
    

    5.2 多维数组

    多维ndarray中,每一维都叫一个轴axis。在ndarray中轴axis是非常重要的,有很多对于ndarray对象的运算都是基于axis进行,比如sum、mean等都会有一个axis参数(针对对这个轴axis进行某些运算操作),后续将会详细介绍。
    对于多维数组,因为每一个轴都有一个索引,所以这些索引由逗号进行分割,例如:

    >>> x = np.arange(0, 100, 5).reshape(4, 5)
    >>> x
    array([[ 0,  5, 10, 15, 20],
           [25, 30, 35, 40, 45],
           [50, 55, 60, 65, 70],
           [75, 80, 85, 90, 95]])
    >>> x[1,2]      #第1行,第2列
    35
    >>> x[1:4, 3]    #第1行到第3行中所有第3列的元素
    array([40, 65, 90])
    >>> x[:, 4]      #所有行中的所有第4列的元素
    array([20, 45, 70, 95])
    >>> x[0:3, :]    #第0行到第三行中所有列的元素
    array([[ 0,  5, 10, 15, 20],
           [25, 30, 35, 40, 45],
           [50, 55, 60, 65, 70]])
    

    需要注意的是

    1. 当提供的索引比轴数少时,缺失的索引表示整个切片(只能缺失后边的轴)
    2. 当提供的索引为:时,也表示整个切片
    3. 可以使用...代替几个连续的:索引
    >>> x[1:3]    #缺失第二个轴
    array([[25, 30, 35, 40, 45],
           [50, 55, 60, 65, 70]])
    >>> x[:, 0:4]      #第一个轴是 :
    array([[ 0,  5, 10, 15],
           [25, 30, 35, 40],
           [50, 55, 60, 65],
           [75, 80, 85, 90]])
    >>> x[..., 0:4]    #...代表了第一个轴的 : 索引
    array([[ 0,  5, 10, 15],
           [25, 30, 35, 40],
           [50, 55, 60, 65],
           [75, 80, 85, 90]])
    

    多维数组的迭代
    可以使用ndarray的flat属性迭代数组中每一个元素

    >>> for item in x.flat:
    ...     print item,
    ...
    0 5 10 15 20 25 30 35 40 45 50 55 60 65 70 75 80 85 90 95
    

    相关文章

      网友评论

      本文标题:numpy基础——ndarray对象

      本文链接:https://www.haomeiwen.com/subject/izvsettx.html