pandas之loc iloc ix

首先,介绍这三种方法的概述: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

1.loc

其实,对于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 '''

2.iloc

对于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 '''

3.ix

注: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。

4.在Dataframe中使用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://stackoverflow.com/questions/31593201/pandas-iloc-vs-ix-vs-loc-explanation-how-are-they-different

转载于https://blog.csdn.net/anshuai_aw1/article/details/82801435

相关文章
相关标签/搜索