在上一篇博客中,我们已经仔细讲解了iloc和loc,只是简单了提到了ix。这是因为相比于前2者,ix更复杂,也更让人迷惑。
因此,本篇博客通过例子的解释试图来描述清楚ix,尤其是与iloc和loc的联系。
首先,再次介绍这三种方法的概述:
- loc gets rows (or columns) with particular labels from the index. loc从索引中获取具有特定标签的行(或列)。
- iloc gets rows (or columns) at particular positions in the index (so it only takes integers). iloc在索引中的特定位置获取行(或列)(因此它只接受整数)。
- 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一样的行为。(这句话有些绕口,没关系,关于ix特点,后面会详细讲解)
1 使用ix切分Series
请注意:在pandas版本0.20.0及其以后版本中,ix已经不被推荐使用,建议采用iloc和loc实现ix。这是为什么呢?这是由于ix的复杂特点可能使ix使用起来有些棘手:
- 如果索引是整数类型,则ix将仅使用基于标签的索引,而不会回退到基于位置的索引。如果标签不在索引中,则会引发错误。
- 如果索引不仅包含整数,则给定一个整数,ix将立即使用基于位置的索引而不是基于标签的索引。但是,如果ix被赋予另一种类型(例如字符串),则它可以使用基于标签的索引。
接下来举例说明这2个特点。
1.1 特点1举例
> 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仅使用基于标签的索引,而不会回退到基于位置的索引。如果标签不在索引中,则会引发错误。
1.2 特点2举例
接着例子1来说,如果我们的索引是一个混合的类型,即不仅仅包括整型,也包括其他类型,如字符类型。那么,给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。
2 在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个“繁琐”的特点。
3 参考文献
https://stackoverflow.com/questions/31593201/pandas-iloc-vs-ix-vs-loc-explanation-how-are-they-different
pandas,ix
更新动态
- 凤飞飞《我们的主题曲》飞跃制作[正版原抓WAV+CUE]
- 刘嘉亮《亮情歌2》[WAV+CUE][1G]
- 红馆40·谭咏麟《歌者恋歌浓情30年演唱会》3CD[低速原抓WAV+CUE][1.8G]
- 刘纬武《睡眠宝宝竖琴童谣 吉卜力工作室 白噪音安抚》[320K/MP3][193.25MB]
- 【轻音乐】曼托凡尼乐团《精选辑》2CD.1998[FLAC+CUE整轨]
- 邝美云《心中有爱》1989年香港DMIJP版1MTO东芝首版[WAV+CUE]
- 群星《情叹-发烧女声DSD》天籁女声发烧碟[WAV+CUE]
- 刘纬武《睡眠宝宝竖琴童谣 吉卜力工作室 白噪音安抚》[FLAC/分轨][748.03MB]
- 理想混蛋《Origin Sessions》[320K/MP3][37.47MB]
- 公馆青少年《我其实一点都不酷》[320K/MP3][78.78MB]
- 群星《情叹-发烧男声DSD》最值得珍藏的完美男声[WAV+CUE]
- 群星《国韵飘香·贵妃醉酒HQCD黑胶王》2CD[WAV]
- 卫兰《DAUGHTER》【低速原抓WAV+CUE】
- 公馆青少年《我其实一点都不酷》[FLAC/分轨][398.22MB]
- ZWEI《迟暮的花 (Explicit)》[320K/MP3][57.16MB]