美文网首页
第4章 Numpy基础(2)

第4章 Numpy基础(2)

作者: whybask | 来源:发表于2019-10-03 08:56 被阅读0次

    以下内容主要学习自《利用Python进行数据分析》

    第4章 NumPy基础(2)

    NumPy是Numerical Python的简称,它是目前Python数值计算中最为重要的基础包。大多数计算包都提供了基于Numpy的科学函数功能,将NumPy的数组对象作为数据交换的通用语言。

    本章将介绍NumPy数组的基础操作。虽然深入理解NumPy对于大部分数据分析应用并不是必需的,但是精通基于数组的编程和思维是成为Python科学计算专家的第一步

    NumPy-2

    ndarray索引与切片

    Numpy.ndarray的索引与切片是一个值得学习的话题。有很多方式可以让你选中数据的子集或某个单一元素。

    所谓“索引”,就是通过单一的索引号,得到ndarray的部分数据;所谓“切片”,就是通过索引号段,得到ndarray的部分数据。索引可以取得原数组降维的部分数据,而切片不会降低维度,而是得到一个维度相同的子集

    如果熟悉Python的列表操作,那么很容易掌握ndarray的索引与切片,因为语法是相似的。

    索引

    通过索引获得单一的元素

    NumPy的索引语法与Python列表的索引语法是一样的。如下是对一维数组进行索引:

    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]  #一维数组的索引
    Out[3]: 5
    

    如果要从二维数组(或多维数组)中取得单一元素,那么就要提供多个索引值。如下是对二维数组进行索引:

    In [4]: arr = arr.reshape(2, 5)
    
    In [5]: arr
    Out[5]:
    array([[0, 1, 2, 3, 4],
           [5, 6, 7, 8, 9]])
    
    In [6]: arr[1][3]  # 二维数组的索引
    Out[6]: 8
    
    In [7]: arr[1, 3]  # 尽管索引语法不同,但索引效果一样
    Out[7]: 8
    
    通过索引获得ndarray的子集

    可以从二维(或多维)数组中,获得ndarray的自己,方法是在多维数组中,如果省略后续索引值,返回的对象将是降低一个维度的数组。

    # 生成一个维度为(2,3,4)的三维数组
    In [1]: arr = np.arange(24).reshape(2, 3, 4)
    
    In [2]: arr
    Out[2]:
    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]]])
    
    In [3]: arr[0]  # 返回第1维、索引号为0的子集,返回的将是二维数组
    Out[3]:
    array([[ 0,  1,  2,  3],
           [ 4,  5,  6,  7],
           [ 8,  9, 10, 11]])
    
    In [4]: arr[0][1]  # 返回一维数组
    Out[4]: array([4, 5, 6, 7])
    

    切片

    一维数组的切片

    与Python列表类似,NumPy数组可以通过相似的语法对数组进行切片。

    In[1]: arr = np.arange(10)
    
    In[2]: arr
    Out[2]: array([0, 1, 2, 3, 4, 5, 6, 7, 8, 9])
    
    In[3]: sub = arr[5:8]  # 通过切片获取部分数据
    
    In[4]: sub
    Out[4]: array([5, 6, 7])
    
    In [5]: sub.shape  # sub是一个有三个元素的一维数组
    Out[5]: (3,)
    
    In[6]: sub[0:2] = 12  # 对切片赋值,就是对切片中的每一个元素赋值
    
    In[7]: arr
    Out[7]: array([ 0,  1,  2,  3,  4, 12, 12, 7,  8,  9])
    

    注意,区别于Python的内建列表,ndarray的切片是原数组的视图,这意味着数据并不是被复制了,任何对于视图的修改都会反映到原数组上。这是因为NumPy被设计成适合处理非常大的数组,你可以想象如果NumPy持续复制数据会引起内存和性能问题。

    如果你是NumPy新手,你可能对此感到惊讶,因为其他的编程语言都是急切地复制数据。如果你坚持要得到一份数组切片的拷贝,而不是一份视图的话,可以试用ndarray.copy()方法显式地复制数据。

    In [8]: sub = arr[0:3].copy()  # 显式地复制数据
    
    In [9]: sub
    Out[9]: array([0, 1, 2])
    
    In [10]: sub[0:3] = 99
    
    In [11]: sub
    Out[11]: array([99, 99, 99])
    
    # 通过复制的子集,不会影响原数组
    In [12]: arr
    Out[12]: array([ 0,  1,  2,  3,  4, 13, 13, 12,  8,  9])
    
    多维数组的切片
    In [1]: arr = np.arange(12).reshape(3,4)
    
    In [2]: arr  # 一个3X4的二维数组
    Out[2]:
    array([[ 0,  1,  2,  3],
           [ 4,  5,  6,  7],
           [ 8,  9, 10, 11]])
    
    # 对二维数组进行切片,得到一个子集
    # 1:3表示从第2行开始,取3-1=2行
    # 2:4表示从第3列开始,取4-2=2列
    In [3]: arr[1:3, 2:4]
    Out[3]:
    array([[ 6,  7],
           [10, 11]])
    

    注意:索引可以取得原数组降维的部分数据,而切片不会降低维度,而是得到一个维度相同的子集。妥善地混合索引和切片,就可以得到低维度的切片。

    In [4]: arr[1, 1:3]  # 获取第2行,2、3列数据
    Out[4]: array([5, 6])
    

    单独一个冒号表示选择整个轴上的数组,并且对原数组的切片赋值,那么原数组也会被赋值。这也是因为NumPy被设计成适合处理非常大的数组,因此缺省是按地址引用。

    In [1]: arr = np.arange(12).reshape(3,4)
    
    In [2: arr
    Out[2]:
    array([[ 0,  1,  2,  3],
           [ 4,  5,  6,  7],
           [ 8,  9, 10, 11]])
    
    # 获取所有行、第1列的切片
    In [3]: sub = arr[:, :1]
    
    In [4]: sub
    Out[4]:
    array([[0],
           [4],
           [8]])
    
    # 把切片中的所有元素赋值为0
    In [5]: sub[:,:] = 0
    
    # 对切片的赋值,会影响到原数组
    In [6]: arr
    Out[6]:
    array([[ 0,  1,  2,  3],
           [ 0,  5,  6,  7],
           [ 0,  9, 10, 11]])
    

    神奇索引

    神奇索引这个词很容易让人误解,它是NumPy的一个术语。简单来讲,神奇索引的目的是用整数数组对ndarray数据进行索引。

    假设我们有一个8X4的数组:

    In [1]: arr = np.empty((8,4))
    
    In [2]: for i in range(8):
        ...:     arr[i] = i+1
    
    In [3]: arr
    Out[3]:
    array([[1., 1., 1., 1.],
           [2., 2., 2., 2.],
           [3., 3., 3., 3.],
           [4., 4., 4., 4.],
           [5., 5., 5., 5.],
           [6., 6., 6., 6.],
           [7., 7., 7., 7.],
           [8., 8., 8., 8.]])
    

    如果我们要从如上的数组中,选择第5、4、1、7行组成的子集,那么可以传递[4,3,0,6]来得到(注意数组下标从0开始)

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

    如果使用负数索引,将从尾部进行选择:

    In [5]: arr[[-3, -5, -7]]
    Out[5]:
    array([[6., 6., 6., 6.],
           [4., 4., 4., 4.],
           [2., 2., 2., 2.]])
    

    注意上面的例子,原数组是二维的,但传入了一个索引维度,所以是得到了降维后的子集。如果传入两个索引,将得到一维数组。

    In [1]: arr = np.arange(12).reshape(3,4)
    
    In [2]: arr
    Out[2]:
    array([[ 0,  1,  2,  3],
           [ 4,  5,  6,  7],
           [ 8,  9, 10, 11]])
    
    # 选去第1行第2个元素、以及第3行第4个元素。
    In [3]: arr[[0,2], [1, 3]]
    Out[3]: array([ 1, 11])
    

    请牢记:神奇索引与切片不同,它总是将数据复制到一个新的数组中。

    布尔索引

    假设我们有7X3的数据,这7行数据数据属于3个人,如下示例:

    In [1]: names = np.array(['张三', '王五', '李四', '张三', '王五', '王五', '李四'])
    
    # 生成一个7X3的数组,数组中的每个元素是0~10的随机数
    In [2]: data = np.random.randint(low=0, high=10, size=(7,3))
    
    In [3]: data
    Out[3]:
    array([[4, 0, 2],
           [8, 1, 5],
           [3, 3, 1],
           [4, 9, 3],
           [3, 7, 3],
           [7, 8, 4],
           [5, 4, 7]])
    

    用names数组与字符串'张三'比较会产生一个布尔值数组:

    In [4]: names == '张三'
    Out[4]: array([ True, False, False,  True, False, False, False])
    

    如果把这个布尔值数组当作“神奇索引”,传递给data数组,会得到如下结果

    In [5]: data[names == '张三']
    Out[5]:
    array([[4, 0, 2],
           [4, 9, 3]])
    

    如上,其效果等同于选择出了所有“张三”的行数据。

    ndarray排序

    一维数组的排序

    数组实例可以使用sort方法进行排序。

    In [1]: arr = np.random.randn(6)
    
    In [2]: arr
    Out[2]:
    array([-1.51683294,  0.71207739, -1.91733282, -1.07901923, -0.35628366,
           -0.52888226])
    
    In [3]: arr.sort()
    
    In [4]: arr
    Out[4]:
    array([-1.91733282, -1.51683294, -1.07901923, -0.52888226, -0.35628366,
            0.71207739])
    

    多维数组的排序

    对于多维数组的排序,可以使用NumPy的顶层sort函数,该函数可以接送axis参数,以便按照某一个维度排序。

    In [1]: arr = np.random.randint(-5, 5, (3,4))
    
    In [2]: arr
    Out[2]:
    array([[ 2,  4, -4, -3],
           [-1, -5,  2,  0],
           [-3, -4, -3, -3]])
    
    In [3]: np.sort(arr, axis=0)
    Out[3]:
    array([[-3, -5, -4, -3],
           [-1, -4, -3, -3],
           [ 2,  4,  2,  0]])
    
    In [4]: np.sort(arr, axis=1)
    Out[4]:
    array([[-4, -3,  2,  4],
           [-5, -1,  0,  2],
           [-4, -3, -3, -3]])
    

    相关文章

      网友评论

          本文标题:第4章 Numpy基础(2)

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