美文网首页呆鸟的Python数据分析
《Hello NumPy》系列-切片的花式操作

《Hello NumPy》系列-切片的花式操作

作者: 小一不二三 | 来源:发表于2020-02-13 15:34 被阅读0次
    文章首发:公众号『知秋小梦』

    2020,努力做一个无可替代的人!

    写在前面的话

    NumPy 第二小节,同学们自行复习前面的内容:

    高阶部分篇篇都是干货,建议大家不要错过任何一节内容,最好关注我,或者公众号(同名),方便看到每次的文章推送。

    正文

    先想一个问题,NumPy 的核心是多维数组,List 也是数组,那是否它们的一些特性也是相同的呢?

    List 特性是什么?又忘记了吧?

    我直接贴前面文章的链接啦,注意仔细看:Python 列表与字符串高阶特性

    你也先别急着回答前面的问题,带着问题继续往下看。

    先看一维数组

    首先,先创建一个一维数组:

    # 创建一维数组
    data_arr = np.arange(10)
    
    # 输出
    [0 1 2 3 4 5 6 7 8 9]
    

    0-9的一维数组,我们试着输出数组的后五位数

    # 输出数组的后五位数
    data_arr[-5:]
    data_arr[5:10]
    
    # 输出
    [5 6 7 8 9]
    [5 6 7 8 9]
    

    可以看到,和列表 List 一样,一维数组同样支持切片操作

    不同的是,数组切片是原始数组的视图,视图上的任何修改都会直接反映到源数组上。

    # 修改数组后五位数的值
    data_arr[-5:] = 0
    # 输出
    [0 1 2 3 4 0 0 0 0 0]
    
    # 修改数组奇数位上的值为 -1
    data_arr[::2] = -1
    # 输出
    [-1  1 -1  3 -1  0 -1  0 -1  0]
    

    可以直接通过修改切片结果,也就是视图,从而达到修改源数组值的效果。

    往下看,我们要找出数组值为 -1的所有元素

    # 数组值为 -1的所有元素
    data_arr == -1
    data_arr[data_arr == -1]
    
    # 输出
    [ True False  True False  True False  True False  True False]
    [-1 -1 -1 -1 -1]
    

    通过对 data_arr 进行比较运算输出一个布尔型数组,然后输出布尔值为 True 的结果。

    当然这个例子比较牵强,输出的肯定都是 -1 啦。

    换种比较方式,我们找出数组值大于 0 的所有元素

    # 数组值大于 0 的所有元素
    data_arr[data_arr > 0]
    
    # 输出
    [1 3]
    

    我们发现,数组支持布尔型索引

    在进行数据分析时,布尔类型的数据筛选可以节省很多工作。

    再来看多维数组

    同样的先创建多维数组,这里用到的创建方法不同于上节介绍到的几种方式

    同学们可以了解一下。

    # 通过 randn 函数生成五行三列正态分布的随机数据
    data_arr2d = np.random.randn(5, 3)
    
    # 输出
    [[ 1.13042124 -1.6739234   0.53706167]
     [-0.97661624 -0.27100353  0.00312314]
     [-0.01815399 -1.11894791  0.54558887]
     [-0.90802724  0.07955776 -0.26139345]
     [-0.59722727 -0.54188117  1.1033876 ]]
    

    random 函数还有 rand()、random()、randint() 等多种方法

    我们这里通过 randn() 方法生成正态分布的随机数据。

    和一维数组一样,我们试着进行切片操作

    # 输出五行三列数据的第一行数据
    data_arr2d[:1]
    # 输出
    [[ 1.13042124 -1.6739234   0.53706167]]
    
    # 输出五行三列数据的第二行第二列数据
    data_arr2d[1:2, 1:2]
    # 输出
    [[-0.27100353]]
    
    # 输出五行三列数据的奇数行奇数列数据
    data_arr2d[::2, ::2]
    # 输出
    [[ 1.13042124  0.53706167]
     [-0.01815399  0.54558887]
     [-0.59722727  1.1033876 ]]
    

    可以看到,同一维数组切片一样,二维数组是在一维数组上再进行切片。

    解释一下, :: 表示所有行, ::2 表示从第0行开始每隔2行取数

    当然,我们也可以通过索引+切片的方式混合取值

    # 输出五行三列数据的第二行的奇数列数据
    data_arr2d[1, ::2]
    # 输出
    [-0.97661624  0.00312314]
    
    # 输出五行三列数据的奇数行的第二列数据
    data_arr2d[::2, 1]
    # 输出
    [-1.6739234  -1.11894791 -0.54188117]
    

    通过索引确定二维数组的行,然后通过切片确定列,也可以取到相应的值;反之,切片确定行、索引确定列同样适用。

    注意:Python 中索引是从0开始计数(即第一行)


    假设上面的五行三列数据分别代表【A,B,C,D,E】 的语文、数学、英语三科成绩,我们通过姓名数组对应起来

    # 创建数组,表示【A,B,C,D,E】
    name_arr = np.array(['A', 'B', 'C', 'D', 'E'])
    
    # 输出
    ['A' 'B' 'C' 'D' 'E']
    

    这样的话,数据的行对应我们的【A,B,C,D,E】,数据的列对应语文、数学、英语三科成绩。

    我们试着输出 C 的三科成绩

    通过 name_arr 确定行,输出所有列的值

    # C 的三科成绩
    data_arr2d[name_arr == 'C']
    
    # 输出
    [[-0.01815399 -1.11894791  0.54558887]]
    

    再试着输出 A、C、D、E 的三科成绩

    通过 name_arr 确定 A、C、D、E 的行,输出所有列的值。
    这里可以通过取反,即 非B 的所有行

    # A、C、D、E 的三科成绩
    data_arr2d[name_arr != 'B']
    # A、C、D、E 的三科成绩
    data_arr2d[~(name_arr == 'B')]
    
    # 输出
    [[ 1.13042124 -1.6739234   0.53706167]
     [-0.01815399 -1.11894791  0.54558887]
     [-0.90802724  0.07955776 -0.26139345]
     [-0.59722727 -0.54188117  1.1033876 ]]
    

    可以发现,两种表达方式都可,既可以使用 不等于符号 (!=),也可以通过波浪号 (~) 进行取反操作

    需要注意的是,Python 2.7.13以上版本用波浪线(~)代替了负号(-)


    上面的都是单条件表达,如果我们想要多个条件呢?

    例如如果我们想要 输出 A、C同学的三科成绩?

    通过 name_arr 确定 A、C 行

    # 输出 A、C同学的三科成绩
    data_arr2d[(name_arr == 'A') | (name_arr == 'C')]
    
    # 输出
    [[ 1.13042124 -1.6739234   0.53706167]
     [-0.01815399 -1.11894791  0.54558887]]
    

    如果我们只想要输出在 0-1之间的所有数据呢?

    通过 data_arr2d 值筛选确定值在 0-1 之间的数据

    # 输出在 0-1之间的所有数据
    data_arr2d[(data_arr2d > 0) & (data_arr2d < 1)]
    
    # 输出
    [0.53706167 0.00312314 0.54558887 0.07955776]
    

    可以看到,在组合应用多个布尔条件,使用 &(与)、|(或)、!(非)算术运算符

    特别注意的是:Python 关键字 and 和 or 在布尔型数组中无效

    最后一个问题,如果我们想要把所有负数用0代替呢?

    通过筛选选出所有小于0的值,通过修改视图修改源数组的值

    # 负数全部用0代替
    data_arr2d[data_arr2d < 0] = 0
    
    # 输出
    [[1.13042124 0.         0.53706167]
     [0.         0.         0.00312314]
     [0.         0.         0.54558887]
     [0.         0.07955776 0.        ]
     [0.         0.         1.1033876 ]]
    

    最后这个问题就有点数据清洗的思想了,小于0 的数据属于异常值,对于异常值我们可以通过剔除该数据、用其他值填充等方式处理

    总结一下:

    如果你没有看懂今天的逻辑,最后的总结非常有必要,细品一下

    首先,通过列表的相关特性,我们从一维、二维分别分析数组的相关特性。

    列表切片:通过起始下标、结束下标、步长等参数进行切片操作。

    一维数组:在列表切片的基础上,多了布尔型索引、修改视图结果的功能

    二维数组:在一位切片的功能上,新增第二维切片,且同时支持索引+切片的功能。

    最后,别忘了刚开始提出的问题,List 和 NumPy 有哪些异同?

    同学们自己回答,看完文章回答这个问题应该很简单。


    写在后面的话

    NumPy 第二节内容,如果你理解了列表的切片,其实这个就很好理解了。

    所以还是那句话,最基础的东西,都是在给以后的高阶内容打基础。

    NumPy 也是,理解了 NumPy,在以后的数据清洗、算法推导有很大帮助!

    碎碎念一下

    最全的干货已经开始了,大家不要掉队啊。

    数据分析的重点已经开始了,加油鸭!

    原创不易,欢迎点赞噢

    文章首发:公众号【知秋小梦】

    文章同步:掘金,简书

    原文链接:《Hello NumPy》系列-切片的花式操作


    相关文章

      网友评论

        本文标题:《Hello NumPy》系列-切片的花式操作

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