评论 ( 6 )
Pandas 快速数据筛选
Pandas 中数据选择是非常常用且非常重要的基础操作,但是 Pandas 中提供的方法较多且应用灵活,很容易让初学者搞混,尤其是条件筛选或者进行一些局部计算赋值的操作,还是有一定的技巧性。本文总结了一些数据选择方法,包括基础选择和条件选择两大块,内容相对精简且尽量做到一目了然,主要用于速查。
1.构建数据
先构建一套样例数据,以辅助对下面内容的理解。
1 2 3 4 5 6 7 | import numpy as np import pandas as pd dates = pd.date_range('20190101', periods=6) np.random.seed(1) df = pd.DataFrame(np.random.randn(6,4), index=dates, columns=list('ABCD')) df |
A | B | C | D | |
---|---|---|---|---|
2019-01-01 | 1.624345 | -0.611756 | -0.528172 | -1.072969 |
2019-01-02 | 0.865408 | -2.301539 | 1.744812 | -0.761207 |
2019-01-03 | 0.319039 | -0.249370 | 1.462108 | -2.060141 |
2019-01-04 | -0.322417 | -0.384054 | 1.133769 | -1.099891 |
2019-01-05 | -0.172428 | -0.877858 | 0.042214 | 0.582815 |
2019-01-06 | -1.100619 | 1.144724 | 0.901591 | 0.502494 |
2.基础选择
基础选择速查表
方法 | 说明 | 是否可更新值 | 示例 |
---|---|---|---|
[]/[[]] | 一列或多列 | 是 | df[‘A’] df[[‘A’, ‘B’]] |
[:] | 切取行 | 是 | df[0:] df[1:2] df[‘A’][0] 注:切片不包含最后一项 |
loc[,] | 通过索引标签 (连续) 和列标签选择 | 是 | df.loc[‘2019-01-01’] df.loc[‘2019-01-02′,’A’] df.loc[‘2019-01-01′:’2019-01-03′,’A’:’C’] df.loc[:,[‘C’,’A’]] 注:切片包含最后一项 |
reindex() | 通过索引标签 (不连续) 和列标签选择 | 否 | df.reindex(index=ind_list, columns=col_list) df.reindex(ind_list, axis=’index’) df.reindex(col_list, axis=’columns’) df.reindex(index=ind_list, columns=[‘A’,’E’], fill_value=’-999′)(可多出不存在的索引或列,并可选择填充) 注:reindex 不识别字符串形式的时间,因此 ind_list=[‘2019-01-01’, ‘2019-01-03’] 会被认为是新的索引,可使用时间函数转一下 ind_list=pd.to_datetime([‘2019-01-01’, ‘2019-01-03’]) |
iloc[,] | 通过行列位置选择 | 是 | df.iloc[0′] df.iloc[0,0] df.iloc[0:2,[0,3]] df.loc[:,[3,1]] 注:切片不包含最后一项 |
at[,] | 类似 loc,通过索引标签和列标签选择,只能获取一个值 | 是 | df.at[pd.to_datetime(‘2019-01-01′),’A’] 注:at 不支持字符串时间,需转换 |
iat[,] | 类似 iloc,通过行列位置选择,只能选取一个值 | 是 | df.iat[0,2] |
ix[] | 通过混合行列标签和位置选择(基于 loc 和 iloc 的混合, 将弃用,不推荐使用) | 是 | df.ix[‘2019-01-01′:’2019-01-03’,0:3] 注:可混合标签和位置来选择,基于标签等同于 loc,切片包含最后一项,基于位置等同于 iloc,切片不包含最后一项。 |
xs() | 通过行列标签选择,多用于层次化索引 | 否 | df.xs(‘2019-01-01’) df.xs(‘A’, axis=1) df.xs((‘index1’, ‘index2’)) df.xs(‘index2’, level=2) df.xs((‘index1’, 2), level=[0, ‘third’])(选择第一层第三层索引) |
get_value() | 通过行列标签选取单一值(将弃用,不推荐使用,可用 at 或 iat 替代) | 否 | df.get_value(pd.to_datetime(‘2019-01-06’), ‘A’) 注:该方法不识别字符串形式的时间。 |
set_value() | 通过行列标签选取单一目标并更新为指定数值(将弃用,不推荐使用,可用 at 或 iat 替代) | 是 | df.set_value(pd.to_datetime(‘2019-01-06’), ‘A’, -999) 注:该方法不识别字符串形式的时间。 |
get_loc() | (相关)通过标签获取位置 | 否 | df.index.get_loc(‘2019-01-03’) df.columns.get_loc(‘C’) |
get_slice_bound() | (相关)通过标签获取切片位置 | 否 | df.columns.get_slice_bound(‘C’, ‘left’, ‘loc’) df.index.get_slice_bound(‘2019-01-03’, ‘right’, ‘ix’) |
3.条件筛选
3.1.条件构建
条件筛选的本质是通过条件构造一个布尔型索引掩码,然后再进行其他操作,如过滤切分,赋值等。
1 2 3 | mask = (df.A>0) & (df.B<0) & (df.C<0) mask |
1 2 3 4 5 6 7 8 | 2019-01-01 True 2019-01-02 False 2019-01-03 False 2019-01-04 False 2019-01-05 False 2019-01-06 False Freq: D, dtype: bool |
还有其他形式的条件构造方式,道理是一样的,如下:
1 2 3 4 5 6 7 8 9 10 11 12 | # 把多个条件分别赋值给多个变量,然后联合 Crit1 = df.A > 0 Crit2 = df.B < 0 Crit3 = df.C < 0 AllCrit = Crit1 & Crit2 & Crit3 # 或者利用reduce内建函数 CritList = [Crit1, Crit2, Crit3] AllCrit = reduce(lambda x,y: x & y, CritList) # 也可构造一个与原df结构一模一样的布尔型掩码,可以使筛选更加细致 df_mask = pd.DataFrame({'A' : [True] * 6, 'B' : [False] * 6,'C' : [True,False] * 3, 'D' : [False] * 6}, index=df.index) |
3.2.pandas 常规的筛选赋值
1 2 3 | # 筛选出满足条件的行 df[mask] |
A | B | C | D | |
---|---|---|---|---|
2019-01-01 | 1.624345 | -0.611756 | -0.528172 | -1.072969 |
1 2 3 4 | # 利用掩码条件进行赋值 df.loc[mask,'D'] = -999 df |
A | B | C | D | |
---|---|---|---|---|
2019-01-01 | 1.624345 | -0.611756 | -0.528172 | -999.000000 |
2019-01-02 | 0.865408 | -2.301539 | 1.744812 | -0.761207 |
2019-01-03 | 0.319039 | -0.249370 | 1.462108 | -2.060141 |
2019-01-04 | -0.322417 | -0.384054 | 1.133769 | -1.099891 |
2019-01-05 | -0.172428 | -0.877858 | 0.042214 | 0.582815 |
2019-01-06 | -1.100619 | 1.144724 | 0.901591 | 0.502494 |
3.3.使用 df.where 方法筛选赋值
1 2 3 | # 仅保留掩码为True位置的值,其他默认置为NaN df.where(df_mask) |
A | B | C | D | |
---|---|---|---|---|
2019-01-01 | 1.624345 | NaN | -0.528172 | NaN |
2019-01-02 | 0.865408 | NaN | NaN | NaN |
2019-01-03 | 0.319039 | NaN | 1.462108 | NaN |
2019-01-04 | -0.322417 | NaN | NaN | NaN |
2019-01-05 | -0.172428 | NaN | 0.042214 | NaN |
2019-01-06 | -1.100619 | NaN | NaN | NaN |
1 2 3 | # 仅保留掩码为True位置的值,其他填充为指定值 df.where(df_mask, 100) |
A | B | C | D | |
---|---|---|---|---|
2019-01-01 | 1.624345 | 100.0 | -0.528172 | 100.0 |
2019-01-02 | 0.865408 | 100.0 | 100.000000 | 100.0 |
2019-01-03 | 0.319039 | 100.0 | 1.462108 | 100.0 |
2019-01-04 | -0.322417 | 100.0 | 100.000000 | 100.0 |
2019-01-05 | -0.172428 | 100.0 | 0.042214 | 100.0 |
2019-01-06 | -1.100619 | 100.0 | 100.000000 | 100.0 |
3.4.使用 np.where 方法筛选赋值
1 2 3 4 | # 利用numpy的where还可以对掩码为true的地方也进行填充,这样几乎生成了一个新的矩阵 new_arr = np.where(df_mask, -100, 100) new_arr |
1 2 3 4 5 6 7 | array([[-100, 100, -100, 100], [-100, 100, 100, 100], [-100, 100, -100, 100], [-100, 100, 100, 100], [-100, 100, -100, 100], [-100, 100, 100, 100]]) |
1 2 3 4 | # 然后按照df的结构重新构造DataFrame数据结构 new_df = pd.DataFrame(new_arr, index=df.index, columns=df.columns) new_df |
A | B | C | D | |
---|---|---|---|---|
2019-01-01 | -100 | 100 | -100 | 100 |
2019-01-02 | -100 | 100 | 100 | 100 |
2019-01-03 | -100 | 100 | -100 | 100 |
2019-01-04 | -100 | 100 | 100 | 100 |
2019-01-05 | -100 | 100 | -100 | 100 |
2019-01-06 | -100 | 100 | 100 | 100 |
3.5.使用 df.isin 方法筛选赋值
1 2 3 4 | alist = [-888, -999] df[df.isin(alist)]=np.nan df |
A | B | C | D | |
---|---|---|---|---|
2019-01-01 | 1.624345 | -0.611756 | -0.528172 | NaN |
2019-01-02 | 0.865408 | -2.301539 | 1.744812 | -0.761207 |
2019-01-03 | 0.319039 | -0.249370 | 1.462108 | -2.060141 |
2019-01-04 | -0.322417 | -0.384054 | 1.133769 | -1.099891 |
2019-01-05 | -0.172428 | -0.877858 | 0.042214 | 0.582815 |
2019-01-06 | -1.100619 | 1.144724 | 0.901591 | 0.502494 |
3.6.缺失值和无效值的条件选择
1 2 3 | # 过滤空值 等同于df.isna() df.isnull() |
A | B | C | D | |
---|---|---|---|---|
2019-01-01 | False | False | False | True |
2019-01-02 | False | False | False | False |
2019-01-03 | False | False | False | False |
2019-01-04 | False | False | False | False |
2019-01-05 | False | False | False | False |
2019-01-06 | False | False | False | False |
1 2 3 | # 过滤非空值 等同于df.notna() df.notnull() |
A | B | C | D | |
---|---|---|---|---|
2019-01-01 | True | True | True | False |
2019-01-02 | True | True | True | True |
2019-01-03 | True | True | True | True |
2019-01-04 | True | True | True | True |
2019-01-05 | True | True | True | True |
2019-01-06 | True | True | True | True |
© 除特别注明外,本站所有文章均为卢明冬的博客原创 , 转载请联系作者。
© 本文链接:https://lumingdong.cn/pandas-quick-search-data-selection.html
© 本文链接:https://lumingdong.cn/pandas-quick-search-data-selection.html
您好,想请问一下如果想从 dataframe 中选取每一行中前 2 的值并进行赋值,该怎么写筛选规则呢?
前 2 的意思是前两列还是前两个最大值 (最小值),你再详细描述一下。
是每一行中排名前 2(最大值)的值。index 同样是日期,筛选出每一行中 2 个最大值,再对这两个最大值进行赋值
我先假定你要赋的值是同一个,我这里用-999 表示。可参考下面的代码:
您好,感谢您的回答,但是我这边输入之后报错 max_7num() got an unexpected keyword argument ‘axis’,您知道是什么原因吗?
你检查下是不是哪里写错了,axis 是 apply 的参数,不是 max_7num 的。