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):

講了這么多應該能理解這些切片了


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM