import seaborn as sns
import pandas as pd
import numpy as np
Pandas Indexing and Selecting
让我们来讨论一下pandas数据的切片和切分(slicing and dicing),类似于R里面的数据框或矩阵取子集。今天我们将复习四个主题:
- 复习基础知识
- 多重索引
- 获取单个值
- 一些不用在意的东西
关于基础知识可以参考: basic indexing ,索引相关可参考 advanced indexing. 但要这些资料会很冗长,他会提供一些你可能都用不到的方法,或者没有必要掌握的技能,自行选择:
复习基础知识
首先,让我们简单回顾一下传统的索引和筛选(indexing and selection)。(我们在pandas基础知识pandas fundamentals中介绍了大部分内容)。首先,以下是我们将要使用的数据(旧的 tips 数据):
这个数据存放在:https://github.com/guipsamora/pandas_exercises/tree/master/07_Visualization/Tips
ls
�[31mCombining DataFrames.ipynb�[m�[m* �[31mPandas Intro to Data Structures.ipynb�[m�[m*
�[31mGroup Operations.ipynb�[m�[m* �[31mRow-Column Transformations.ipynb�[m�[m*
�[31mIndexing and Selecting.ipynb�[m�[m* �[31mtips.csv�[m�[m*
�[31mMisc Functions.ipynb�[m�[m*
tips = pd.read_csv('tips.csv')
tips.head()
del tips['Unnamed: 0']
tips.head(3)
下面介绍4种方式从数据框中获取数据:
- 获取不同的列
# 1) get columns
tips[['total_bill', 'tip']].head()
- 获取不同的行
# 2) get some rows
tips[3:5]
- 根据行名列名获取数据
# 3) select rows and columns based on their name
tips.loc[2:4, 'sex': 'smoker']
- 根据位置信息获取数据
# 4) select rows and columns by their ordering
tips.iloc[1:3, 0:2]
- 根据逻辑值来筛选
# 5) select using a bool series
tips[tips['tip'] > 1].head()
不过这些仅仅是冰山一角。
实际上,当你深入研究pandas的其他功能(functionalities)时,你很可能会涉及到其他几个重要的概念。
Multi-index
这是一个您可能认为不需要的主题--但事实证明它是一个相当频繁的用例(usecase)。
multi-index
背后的最初想法是提供一个框架来处理更高的模糊数据(从而取代panels
)。
但由于一些操作,这变得相当平常。在几乎所有情况下,multi-index都来自groupby's(您几乎不会自己构建或阅读它)。
下面我们举个例子:
tips.head()
mi_tips = tips.groupby(['sex', 'smoker']).agg({'tip': 'mean'})
mi_tips
mi_tips.index
MultiIndex([('Female', 'No'),
('Female', 'Yes'),
( 'Male', 'No'),
( 'Male', 'Yes')],
names=['sex', 'smoker'])
最终,您可以在此类型的数据之上执行大量操作。您还可以执行等效的multi-index操作,如下所示:
mi_tips.loc[('Male', 'No')]
tip 3.113402
Name: (Male, No), dtype: float64
通过这种方式,你会学到很多细节,但是总会有例外。
因此,我一直以来处理这个问题的方法很简单,就是重置索引。
ri_tips = mi_tips.reset_index()
ri_tips
请注意我们现在是如何将值分布到整个column中的。因此,通过这种方式,很容易只选择不吸烟的男性(the male non-smokers):
ri_tips[(ri_tips['smoker'] == 'No') & (ri_tips['sex'] == 'Male')]
处理此问题的另一种方法是只删除某些索引:
ri0_tips = mi_tips.reset_index(level=0)
ri0_tips.loc['Yes']
然后如果再需要用到之前的索引,还可以换回来,参考pull indexes back into the index (通常这个操作使用在某些类型数据合并的过程中)。
ri_tips.set_index(['sex', 'smoker'])
ri0_tips.set_index('sex', append=True)
获取单个值
下一个索引小把戏(indexing trick)主要是关于速度的。它是在获取和设置单一的值(使用后提升计算速度)。这是一个非常简单的问题:
tips.head(3)
当需要获取/设定单个值要用到at
函数
tips.at[0, 'total_bill'] = 9000
tips.head(3)
tips.iat[0, 0]
9000.0
如果您正在修改数据框的单个值,则应该始终使用这些工具。它速度更快,而且是知道您没有搞砸的好方法(经常修改数据可能会导致奇怪的错误)。
所以,为了证明它更快,我们来计时吧!
%%timeit
tips.at[0, 'total_bill'] = 6
6.12 µs ± 46.6 ns per loop (mean ± std. dev. of 7 runs, 100000 loops each)
%%timeit
tips.loc['total_bill', 0] = 6
272 µs ± 4.49 µs per loop (mean ± std. dev. of 7 runs, 1000 loops each)
看上去at的速度比较快。
Where, Masks and Queries
这些都是pandas内置的东西,我个人从来没有用过,主要是因为它们相当多余,而且不经常发生。
他们的速度要快一点。但是感觉可能不值得这样做。所以,如果你想学,就去学吧(文档在here)。如果不是,可能就无关紧要了。
下面让我向您展示如何复制mask功能。
df = pd.DataFrame(np.random.randn(25).reshape((5, 5)))
df.head()
df.where(df > 0)
df[df < 0] = np.NaN
df
小结
这就是我所知道的关于索引的全部内容,并探索所有您需要知道的内容。
如果您有任何问题或意见,请在我的留言!
附:在这方面没有什么特别好的教程,如果你知道有更多更好的,请在留言给我一个教程的链接,感谢!
同步更新于我的个人微信公众号: