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的切片,內部是調用getitem,setitem,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):
講了這么多應該能理解這些切片了