首先,介紹這三種方法的概述:html
loc: loc gets rows (or columns) with particular labels from the index. loc從索引中獲取具備特定標籤的行(或列)。這裏的關鍵是:標籤。標籤的理解就是name名字。flex
iloc: gets rows (or columns) at particular positions in the index (so it only takes integers). iloc在索引中的特定位置獲取行(或列)(所以它只接受整數)。這裏的關鍵是:位置。位置的理解就是排第幾個。spa
ix: usually tries to behave like loc but falls back to behaving like iloc if a label is not present in the index. ix一般會嘗試像loc同樣行爲,但若是索引中不存在標籤,則會退回到像iloc同樣的行爲。.net
其實,對於loc始終堅持一個原則:loc是基於label進行索引的!code
import pandas as pd df1 = pd.DataFrame(data= [[1, 2, 3],[4, 5, 6], [7, 8, 9]], index=[0, 1, 2], columns=['a','b','c']) df2 = pd.DataFrame(data= [[1, 2, 3],[4, 5, 6], [7, 8, 9]], index=['e', 'f', 'g'], columns=['a','b','c']) print(df1) print(df2) ''' df1: a b c 0 1 2 3 1 4 5 6 2 7 8 9 df2: a b c e 1 2 3 f 4 5 6 g 7 8 9 ''' # loc索引行,label是整型數字 print(df1.loc[0]) ''' a 1 b 2 c 3 Name: 0, dtype: int64 ''' # loc索引行,label是字符型 print(df2.loc['e']) ''' a 1 b 2 c 3 Name: 0, dtype: int64 '''
# 若是對df2這麼寫:df2.loc[0]會報錯,由於loc索引的是label,顯然在df2的行的名字中沒有叫0的。 print(df2.loc[0]) ''' TypeError: cannot do slice indexing on <class 'pandas.core.indexes.base.Index'> with these indexers [0] of <class 'int'> ''' # loc索引多行數據 print(df1.loc[1:]) ''' a b c 1 4 5 6 2 7 8 9 ''' # loc索引多列數據 print(df1.loc[:,['a', 'b']]) ''' a b 0 1 2 1 4 5 2 7 8 '''
# df1.loc[:,0:2]這麼寫報錯, 由於loc索引的是label,顯然在df1的列的名字中沒有叫0,1和2的。 print(df1.loc[:,0:2]) ''' TypeError: cannot do slice indexing on <class 'pandas.core.indexes.base.Index'> with these indexers [0] of <class 'int'> ''' # locs索引某些行某些列 print(df1.loc[0:2, ['a', 'b']]) ''' a b 0 1 2 1 4 5 2 7 8 '''
對於iloc始終也堅持一個原則:iloc是基於position進行索引的!orm
import pandas as pd df1 = pd.DataFrame(data= [[1, 2, 3],[4, 5, 6], [7, 8, 9]], index=[0, 1, 2], columns=['a','b','c']) df2 = pd.DataFrame(data= [[1, 2, 3],[4, 5, 6], [7, 8, 9]], index=['e', 'f', 'g'], columns=['a','b','c']) print(df1) print(df2) ''' df1: a b c 0 1 2 3 1 4 5 6 2 7 8 9 df2: a b c e 1 2 3 f 4 5 6 g 7 8 9 '''
# iloc索引行,label是整型數字 print(df1.iloc[0]) ''' a 1 b 2 c 3 Name: 0, dtype: int64 ''' # iloc索引行,label是字符型。若是按照loc的寫法來寫應該是:df2.iloc['e'],顯然這樣報錯,由於iloc不認識label,它是基於位置的。 print(df2.iloc['e']) ''' TypeError: cannot do positional indexing on <class 'pandas.core.indexes.base.Index'> with these indexers [e] of <class 'str'> '''
# iloc索引行,label是字符型。正確的寫法應該以下: # 也就說,不論index是什麼類型的,iloc只能寫位置,也就是整型數字。 print(df2.iloc[0]) ''' a 1 b 2 c 3 Name: e, dtype: int64 ''' # iloc索引多行數據 print(df1.iloc[1:]) ''' a b c 1 4 5 6 2 7 8 9 ''' # iloc索引多列數據 # 若是以下寫法,報錯。 print(df1.iloc[:,['a', 'b']]) ''' TypeError: cannot perform reduce with flexible type '''
# iloc索引多列數據, 正確寫法以下: print(df1.iloc[:,0:2]) ''' a b 0 1 2 1 4 5 2 7 8 ''' # iloc索引某些行某些列 print(df1.iloc[0:2, 0:1]) ''' a 0 1 1 4 '''
注:ix的操做比較複雜,在pandas版本0.20.0及其之後版本中,ix已經不被推薦使用,建議採用iloc和loc實現ix。htm
(1)若是索引是整數類型,則ix將僅使用基於標籤的索引,而不會回退到基於位置的索引。若是標籤不在索引中,則會引起錯誤。blog
(2)若是索引不只包含整數,則給定一個整數,ix將當即使用基於位置的索引而不是基於標籤的索引。可是,若是ix被賦予另外一種類型(例如字符串),則它可使用基於標籤的索引。索引
接下來舉例說明這兩個特色:three
>>> s = pd.Series(np.nan, index=[49,48,47,46,45, 1, 2, 3, 4, 5]) >>> s 49 NaN 48 NaN 47 NaN 46 NaN 45 NaN 1 NaN 2 NaN 3 NaN 4 NaN 5 NaN
如今咱們來看使用整數3切片有什麼結果:
在這個例子中,s.iloc[:3]讀取前3行(由於iloc把3當作是位置position),而s.loc[:3]讀取的是前8行(由於loc把3看做是索引的標籤label)
>>> s.iloc[:3] # slice the first three rows 49 NaN 48 NaN 47 NaN >>> s.loc[:3] # slice up to and including label 3 49 NaN 48 NaN 47 NaN 46 NaN 45 NaN 1 NaN 2 NaN 3 NaN >>> s.ix[:3] # the integer is in the index so s.ix[:3] works like loc 49 NaN 48 NaN 47 NaN 46 NaN 45 NaN 1 NaN 2 NaN 3 NaN
注意:s.ix[:3]返回的結果與s.loc[:3]同樣,這是由於若是series的索引是整型的話,ix會首先去尋找索引中的標籤3而不是去找位置3。
若是,咱們試圖去找一個不在索引中的標籤,好比說是6呢?
>>> s.iloc[:6] 49 NaN 48 NaN 47 NaN 46 NaN 45 NaN 1 NaN >>> s.loc[:6] KeyError: 6 >>> s.ix[:6] KeyError: 6
在上面的例子中,s.iloc[:6]正如咱們所指望的,返回了前6行。而,s.loc[:6]返回了KeyError錯誤,這是由於標籤6並不在索引中。
那麼,s.ix[:6]報錯的緣由是什麼呢?正如咱們在ix的特色1所說的那樣,若是索引只有整數類型,那麼ix僅使用基於標籤的索引,而不會回退到基於位置的索引。若是標籤不在索引中,則會引起錯誤。
若是咱們的索引是一個混合的類型,即不單單包括整型,也包括其餘類型,如字符類型。那麼,給ix一個整型數字,ix會當即使用iloc操做,而不是報KeyError錯誤。
>>> s2 = pd.Series(np.nan, index=['a','b','c','d','e', 1, 2, 3, 4, 5]) >>> s2.index.is_mixed() # index is mix of different types True >>> s2.ix[:6] # now behaves like iloc given integer a NaN b NaN c NaN d NaN e NaN 1 NaN
注意:在這種狀況下,ix也能夠接受非整型,這樣就是loc的操做:
>>> s2.ix[:'c'] # behaves like loc given non-integer a NaN b NaN c NaN
這個例子就說明了ix特色2。
正如前面所介紹的,ix的使用有些複雜。若是僅使用位置或者標籤進行切片,使用iloc或者loc就好了,請避免使用ix。
有時候,在使用Dataframe進行切片時,咱們想混合使用標籤和位置來對行和列進行切片。那麼,應該怎麼操做呢?
舉例,考慮有下述例子中的Dataframe。咱們想獲得直到包含標籤'c'的行和前4列。
>>> df = pd.DataFrame(np.nan, index=list('abcde'), columns=['x','y','z', 8, 9]) >>> df x y z 8 9 a NaN NaN NaN NaN NaN b NaN NaN NaN NaN NaN c NaN NaN NaN NaN NaN d NaN NaN NaN NaN NaN e NaN NaN NaN NaN NaN
在pandas的早期版本(0.20.0)以前,ix能夠很好地實現這個功能。
咱們可使用標籤來切分行,使用位置來切分列(請注意:由於4並非列的名字,由於ix在列上是使用的iloc)。
>>> df.ix[:'c', :4] x y z 8 a NaN NaN NaN NaN b NaN NaN NaN NaN c NaN NaN NaN NaN
在pandas的後來版本中,咱們可使用iloc和其它的一個方法就能夠實現上述功能:
>>> df.iloc[:df.index.get_loc('c') + 1, :4] x y z 8 a NaN NaN NaN NaN b NaN NaN NaN NaN c NaN NaN NaN NaN
get_loc()
是獲得標籤在索引中的位置的方法。請注意,由於使用iloc切片時不包括最後1個點,由於咱們必須加1。
能夠看到,只使用iloc更好用,由於沒必要理會ix的那2個「繁瑣」的特色。
轉載於https://blog.csdn.net/anshuai_aw1/article/details/82801435