• Python array,list,dataframe索引切片操作 2016年07月19日——智浪文档


    array,list,dataframe索引切片操作 2016年07月19日——智浪文档

    list,一维,二维array,datafrme,loc、iloc、ix的简单探讨

    Numpy数组的索引和切片介绍:
    从最基础的list索引开始讲起,我们先上一段代码和结果:

    a = [0,1,2,3,4,5,6,7,8,9]  
    a[:5:-1]   #step < 0,所以start = 9  
    a[0:5:-1]  #指定了start = 0  
    a[1::-1]   #step < 0,所以stop = 0  
    

    输出:

    [9, 8, 7, 6]
    []
    [1, 0]
    

    list切片,在“[]”中都有一般都有两个个“:”分隔符,中文意思是 [开始:结束:步长] 在上面的案例中,步长是-1所以输出的数据就倒序了。没有赋值(start,stop)就默认为0。sep默认为1且值不能为0。

    a[10:20]#前11-20个数
    a[:10:2]#前10个数,每两个取一个
    a[::5]#所有数,每5个取一个
    

    python切片中的高级操作:
    切片的原理分析:
    list的切片,内部是调用getitemsetitem,delitem和slice函数。而slice函数又是和range()函数相关的。
    给切片传递的键是一个特殊的slice对象。该对象拥有可描述所请求切片方位的属性,切片的含义和演示:

    >>> List4 = [1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,20]
    [1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20]
    >>> x = List4[1:10] #x = List4.__getitem__(slice(1,10,None))
    [2, 3, 4, 5, 6, 7, 8, 9, 10]
    >>> List4[1:5]=[100,111,122] #List4.setitem__(slice(1,3,None),100,111,122])
    [1, 100, 111, 122, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20]
    >>> del List4[1:4] #List4.del__delitem__(slice(1,4,None))
    [1, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20]
    >>>
    

    切片的边界问题:

    s=[1,2,3,4]       # S 上界为 0 下界为 4
    s[-100:100]       #返回 [1,2,3,4] -100超出了上界,100超出了下界:等价于 s[0:4]
    s[-100:-200]      #返回 [] -100,-200均超出了上界,自动取上界:等价于s[0:0]
    s[100:200]        #返回 [] 100,200均超出了下界,自动取下界值:等价于s[4:4]
    s[:100]           #返回 [1,2,3,4] 开始值省略表示从第0个开始
    s[0:]             #返回 [1,2,3,4] 结束值为空表示到最后一个结束  
    

    切片的扩展知识:

    >>> id(List4)
    140115516658320
    #直接通过列表来赋值 List5 = List4,指向的内存地址空间是不变的,都是(140115516658320),无论删除List4还是List5这个列表都会被删除,即List4和List5都没有元素了。
    >>> List5 = List4
    >>> List5
    [1, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20]
    >>> List4
    [1, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20]
    >>> id(List5)
    140115516658320
    #但是,通过切片来命名的两个列表他们指向的内存地址编号是不同的,140115516658320 !=  140115516604784
    >>> List6 = List5
    >>> id(List6)
    140115516658320
    >>> List6 = List4[:]
    >>> id(List6)
    140115516604784
    >>> #地址改变
    ... 
    >>>
    

    下面们对扩展进行补充:

    >>> listOfRows = [[1,2,3,4], [5,6,7,8], [9,10,11,12]]
    >>> li = listOfRows
    >>> id(listOfRows)
    206368904L
    >>> id(li)  #两者id一致,引用了同一个对象
    206368904L
    >>> listOfRows[:] = [[row[0], row[3], row[2]] for row in listOfRows]
    >>> listOfRows
    [[1, 4, 3], [5, 8, 7], [9, 12, 11]]
    >>> li  #使用切片赋值,达到预期效果,同一对象跟随改变
    [[1, 4, 3], [5, 8, 7], [9, 12, 11]]
    >>> id(listOfRows)
    206368904L
    >>> id(li) #两者的id都没有变化,说明切片赋值实在原对象上修改
    206368904L
    >>> listOfRows = [[1,2,3,4], [5,6,7,8], [9,10,11,12]]
    >>> li
    [[1, 4, 3], [5, 8, 7], [9, 12, 11]]
    >>> id(li)  #li没有改变
    206368904L
    >>> id(listOfRows)  #两者id不同,说明listOfRows绑定了一个新的对象
    206412488L
    >>> listOfRows
    [[1, 2, 3, 4], [5, 6, 7, 8], [9, 10, 11, 12]]
    

    直接使用 "listOfRows =" 的话,产生了一个新的对象,使用"listOfRows[:] =" 写法。简单地说,使用切片赋值可以修改原对象的类容,而不是创建一个新对象。
    序列(consequence)是 python 中一种数据结构,这种数据结构根据索引来获取序列中的对象。
    python 中含有六种内建序列类:list, tuple, string, unicode, buffer, xrange。其中 xrange 比较特殊,它是一个生成器,其他几个类型具有的一些序列特性对它并不适合。一般说来,具有序列结构的数据类型都可以使用:index, len, max, min, in, +, *, 切片。
    list切片称为步进切片,允许使用第三个元素进行切片它的语法为sequence[起始索引:结束索引:步进值]。口诀就是:“顾头不顾尾”。假如你的第一个索引是“0”,那么你可以省略不写。
    当Python使用切片语法时候就会产生切片对象。扩展的切片语法允许对不同的索引切片操作包括步进切片、多维切片和省略切片。多维切片的语法是sequence[start1:end1,start2:end2],或使用省略号,sequence[…,start1:end1]。切片对象也可以由内建函数slice()。

    二维数组的选取:
    首先我们前面说了 多维数组切片的语法是 sequence[start1:end1,start2:end2,…,startn:endn] 我们用一个3X3的二维数组来演示一下选取问题:

    >>> b  = np.arange(9).reshape(3,3)
    >>> b
    array([[0, 1, 2],
           [3, 4, 5],
           [6, 7, 8]])
    

    数组下标是从0开始,对于数组a,只需要用a[m,n]选取各数组中的元素。对应的位置如下

    [(0,0),(0,1),(0,2)]
    [(1,0),(1,1),(1,2)]
    [(2,0),(2,1),(2,2)]
    

    对于切片二维的语法是sequence[start1:end1,start2:end2]

    >>> b[1:,:2]
    #先从第一个逗号分割输出从1开使行 就是  [(1,0),(1,1),(1,2)]
    # 和 [(2,0),(2,1),(2,2)]
    #拿第一个逗号分割的数据,在进行第二维操作,到2结束的列,输入如下
    array([[3, 4],
           [6, 7]])
    

    基于对步进切片的理解后,二维 和 三维都同样的好理解,而且没有步进那么复杂
    同样可以对切片的元素进行复制操作

    >>> b[1:,:2] = 1 #广播赋值
    >>> b
    array([[0, 1, 2],
           [1, 1, 5],
           [1, 1, 8]])
    >>> b[1:,:2].shape
    (2L, 2L)
    >>> b[1:,:2] = np.arange(2,6).reshape(2,2) #对应赋值
    >>> b
    array([[0, 1, 2],
           [2, 3, 5],
           [4, 5, 8]])
    

    三维的同理,就是sequence[start1:end1,start2:end2]。取单值的时候,a[l,m,n]。
    省略的表示[:]取第n维的所有元素。

    >>> b=np.arange(24).reshape(2,3,4)
    >>> b[1,]
    array([[12, 13, 14, 15],
           [16, 17, 18, 19],
           [20, 21, 22, 23]])
    >>> b[1,2]
    array([20, 21, 22, 23])
    >>> b[1,2,3]
    23
    >>> b[1,:,3]
    array([15, 19, 23])
    >>>  
    

    讲到这里,对于pandas的dataframe 我们就可以使用 iloc 把一个df 看作多维数组进行切片

    >>> b  = np.arange(9).reshape(3,3)
    >>> df = pd.DataFrame(b)
    >>> df.iloc[1,2]
    5
    >>> df.iloc[1:,2]
    1    5
    2    8
    Name: 2, dtype: int32
    >>> df.iloc[1:,:2]
       0  1
    1  3  4
    2  6  7
    >>> df.iloc[1:,:2] = 1#同样的广播赋值
    >>> df
       0  1  2
    0  0  1  2
    1  1  1  5
    2  1  1  8
    

    (妈妈在用不用担心我的df切片了)

    讲一下loc,loc 是根据index 和columns 进行选择的,在df赋值操作中,还是比较推荐这种赋值方式。

    当 index 和 columns 为数值的时候 且是从0 开始我们对比一下:

    >>> b = np.arange(36).reshape(6,6)
    >>> b
    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],
           [24, 25, 26, 27, 28, 29],
           [30, 31, 32, 33, 34, 35]])
    >>> df = pd.DataFrame(b)
    >>> df
        0   1   2   3   4   5
    0   0   1   2   3   4   5
    1   6   7   8   9  10  11
    2  12  13  14  15  16  17
    3  18  19  20  21  22  23
    4  24  25  26  27  28  29
    5  30  31  32  33  34  35
    >>> df.loc[1:,:2]
        0   1   2
    1   6   7   8
    2  12  13  14
    3  18  19  20
    4  24  25  26
    5  30  31  32
    >>> df.iloc[1:,:2]
        0   1
    1   6   7
    2  12  13
    3  18  19
    4  24  25
    5  30  31
    >>> df.iloc[1,2]
    8
    >>> df.loc[1,2]
    8
    >>> 
    

    可以看到 df.loc[1:,:2] 选择了 第2 列的内容,但他的本质不是 range(0,2)他包括了结束的2。 他其实是 >= 关系。对column进行判断 取 大于等于2的列。对于不满足条件后立即终止。

    >>> df.columns  =  [2,1,3,4,0,5]
    >>> df
        2   1   3   4   0   5
    0   0   1   2   3   4   5
    1   6   7   8   9  10  11
    2  12  13  14  15  16  17
    3  18  19  20  21  22  23
    4  24  25  26  27  28  29
    5  30  31  32  33  34  35
    >>> df.loc[1,2]
    6
    >>> df.iloc[1,2]
    8
    >>> 
    >>> df.iloc[1:,:2]
        2   1
    1   6   7
    2  12  13
    3  18  19
    4  24  25
    5  30  31
    >>> df.loc[1:,:2]
        2
    1   6
    2  12
    3  18
    4  24
    5  30
    >>> 
    

    loc 有一个好处就是你可以重新排column的顺序

    >>> df.loc[:,(1,2,3,4)]
        1   2   3   4
    0   1   0   2   3
    1   7   6   8   9
    2  13  12  14  15
    3  19  18  20  21
    4  25  24  26  27
    5  31  30  32  33
    >>> df.iloc[:,(1,2,3,4)]
        1   3   4   0
    0   1   2   3   4
    1   7   8   9  10
    2  13  14  15  16
    3  19  20  21  22
    4  25  26  27  28
    5  31  32  33  34
    >>> 
    

    很神奇把,这个iloc就不好办了,当列名换做了 字母,loc就可以天马行空了。

    ix解决混合选取的问题

    >>> df.ix[:,(1,2,3,4)]
        1   2   3   4
    0   1   0   2   3
    1   7   6   8   9
    2  13  12  14  15
    3  19  18  20  21
    4  25  24  26  27
    5  31  30  32  33
    >>> df.ix[:,:2]
        2
    0   0
    1   6
    2  12
    3  18
    4  24
    5  30
    >>> df.ix[:,:2]
    

    ix简单理解就是当行列都是 数字的时候 ix 随 loc。 如果都是字母的时候 ix自动判断[]内的取值,但是【行,列】不变

    >>> df.loc[:2,:2]
       2
    2  0
    >>> df.iloc[:2,:2]
       2  1
    2  0  1
    1  6  7
    >>> df.ix[:2,:2]
       2
    2  0
    >>> df.index  =  ['a','c','d','b','e','f']
    >>> df.ix[:2,:2]
       2
    a  0
    c  6
    >>> df.iloc[:2,:2]
       2  1
    a  0  1
    c  6  7
    >>> df.loc[:2,:2]  #这里loc就报错了,因为column里面没有数值类型的 
    Traceback (most recent call last):
    

    讲了这么多应该能理解这些切片了

  • 相关阅读:
    Algs4-2.3.31运行时间直方图
    Algs4-2.3.30极端情况-各种分布排列时的快排性能
    LintCode Python 简单级题目 111.爬楼梯 (斐波纳契数列 青蛙跳)
    LintCode Python 简单级题目 167.链表求和
    LintCode Python 简单级题目 经典二分查找问题
    LintCode Python 入门级题目 删除链表元素、整数列表排序
    LintCode Python 入门级题目 斐波纳契数列
    LintCode Python 入门级题目 二叉树的最大节点
    Python HTMLTestRunner生成网页自动化测试报告时中文编码报错UnicodeDecodeError: 'ascii' codec can't decode byte 0xe6
    Python的内置函数open()的注意事项
  • 原文地址:https://www.cnblogs.com/zhilangtaosha/p/5685727.html
Copyright © 2020-2023  润新知