Pandas 速查:数据选择

Pandas 中数据选择是非常常用且非常重要的基础操作,但是 Pandas 中提供的方法较多且应用灵活,很容易让初学者搞混,尤其是条件筛选或者进行一些局部计算赋值的操作,还是具有一定的技巧性。本文总结了一些数据选择方法,包括基础选择和条件选择两大块,内容相对精简且尽量做到一目了然,主要用于速查。

1.构建数据

先构建一套样例数据,以辅助对下面内容的理解。

 ABCD
2019-01-011.624345-0.611756-0.528172-1.072969
2019-01-020.865408-2.3015391.744812-0.761207
2019-01-030.319039-0.2493701.462108-2.060141
2019-01-04-0.322417-0.3840541.133769-1.099891
2019-01-05-0.172428-0.8778580.0422140.582815
2019-01-06-1.1006191.1447240.9015910.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.条件构建

条件筛选的本质是通过条件构造一个布尔型索引掩码,然后再进行其他操作,如过滤切分,赋值等。

还有其他形式的条件构造方式,道理是一样的,如下:

3.2.pandas常规的筛选赋值

 ABCD
2019-01-011.624345-0.611756-0.528172-1.072969
 ABCD
2019-01-011.624345-0.611756-0.528172-999.000000
2019-01-020.865408-2.3015391.744812-0.761207
2019-01-030.319039-0.2493701.462108-2.060141
2019-01-04-0.322417-0.3840541.133769-1.099891
2019-01-05-0.172428-0.8778580.0422140.582815
2019-01-06-1.1006191.1447240.9015910.502494

3.3.使用df.where()方法筛选赋值

 ABCD
2019-01-011.624345NaN-0.528172NaN
2019-01-020.865408NaNNaNNaN
2019-01-030.319039NaN1.462108NaN
2019-01-04-0.322417NaNNaNNaN
2019-01-05-0.172428NaN0.042214NaN
2019-01-06-1.100619NaNNaNNaN
 ABCD
2019-01-011.624345100.0-0.528172100.0
2019-01-020.865408100.0100.000000100.0
2019-01-030.319039100.01.462108100.0
2019-01-04-0.322417100.0100.000000100.0
2019-01-05-0.172428100.00.042214100.0
2019-01-06-1.100619100.0100.000000100.0

3.4.使用np.where()方法筛选赋值

 ABCD
2019-01-01-100100-100100
2019-01-02-100100100100
2019-01-03-100100-100100
2019-01-04-100100100100
2019-01-05-100100-100100
2019-01-06-100100100100

3.5.使用df.isin()方法筛选赋值

 ABCD
2019-01-011.624345-0.611756-0.528172NaN
2019-01-020.865408-2.3015391.744812-0.761207
2019-01-030.319039-0.2493701.462108-2.060141
2019-01-04-0.322417-0.3840541.133769-1.099891
2019-01-05-0.172428-0.8778580.0422140.582815
2019-01-06-1.1006191.1447240.9015910.502494

3.6.缺失值和无效值的条件选择

 ABCD
2019-01-01FalseFalseFalseTrue
2019-01-02FalseFalseFalseFalse
2019-01-03FalseFalseFalseFalse
2019-01-04FalseFalseFalseFalse
2019-01-05FalseFalseFalseFalse
2019-01-06FalseFalseFalseFalse
 ABCD
2019-01-01TrueTrueTrueFalse
2019-01-02TrueTrueTrueTrue
2019-01-03TrueTrueTrueTrue
2019-01-04TrueTrueTrueTrue
2019-01-05TrueTrueTrueTrue
2019-01-06TrueTrueTrueTrue
© 除特别注明外,本站所有文章均为卢明冬的博客原创 , 转载请注明作者和文章链接。
© 本文链接:https://lumingdong.cn/pandas-quick-search-data-selection.html
卢明冬

大千世界,人生百态,世事万物,皆无所固形。 行走于世,自当因变而变,写此文,以自省。 人性不离根泽,形之百变,亦可应万物。 凡人之处世,皆不能守固而据,应思变而存。 既可谨言慎行指点江山,又可放浪形骸鲜衣怒马, 既可朝九晚五废寝忘食,又可浪迹天涯四海为家。 随形而居,随意而为,静则思动,动则思远。 虽困于束缚,又能借力束缚,虽惘于迷思,又能获于迷思。 看山是山,看水是水,有酒学仙,无酒学佛。 心存根本,又何惧变乎?

评论 ( 8 )
  1. ivy
    2020年4月17日 at 下午5:38
    回复

    您好,想请问一下如果想从 dataframe 中选取每一行中前 2 的值并进行赋值,该怎么写筛选规则呢?

    • 卢明冬
      卢明冬
      2020年4月17日 at 下午6:15
      回复

      前 2 的意思是前两列还是前两个最大值 (最小值),你再详细描述一下。

      • Ivy
        2020年4月17日 at 下午6:23
        回复

        是每一行中排名前 2(最大值)的值。index 同样是日期,筛选出每一行中 2 个最大值,再对这两个最大值进行赋值

        • 卢明冬
          卢明冬
          2020年4月17日 at 下午9:37
          回复

          我先假定你要赋的值是同一个,我这里用-999 表示。可参考下面的代码:

          def max_2num(row):
              return row.sort_values(ascending=False)[:2]
          df[~df.apply(max_2num, axis=1).isnull()]=-999
          • IVY
            2020年4月17日 at 下午11:26

            您好,感谢您的回答,但是我这边输入之后报错 max_7num() got an unexpected keyword argument 'axis',您知道是什么原因吗?

          • 卢明冬
            卢明冬
            2020年4月18日 at 上午10:41

            你检查下是不是哪里写错了,axis 是 apply 的参数,不是 max_7num 的。

  2. IVY
    2020年4月18日 at 上午10:53
    回复

    def max_7num(row):
    return row.sort_values(axis=1, ascending=False)[:7]
    a = factor_M[~factor_M.apply(max_7num, axis=1).isnull()]=-0.1487
    a.head()

    这样写进去后,还是会报错
    TypeError: max_7num() got an unexpected keyword argument 'axis'
    factor_M 是这样的:

    1 2 3 4 5 6 7 8 9 10 11 12 13
    date
    2018-03-21 0.745490 -0.614057 0.665211 -0.266310 0.252185 -0.162905 -0.210330 0.298028 0.796969 1.124617 0.309529 -0.187716 0.033906
    2018-03-22 0.418193 -0.784872 0.698238 0.115520 -0.144889 0.827475 -0.124872 0.267221 -0.281145 0.996271 0.030552 -0.462186 0.033906
    2018-03-23 1.108164 -0.096835 2.002352 0.773394 0.423017 0.635593 -0.075009 1.332419 0.521108 1.136174 0.789308 -0.140989 0.033906
    2018-03-24 0.531709 -0.099896 3.095136 0.054967 0.564072 0.182563 0.326077 1.694875 0.899882 1.187890 1.166396 -0.141072 0.033906
    2018-03-25 -0.094013 -0.308356 2.798438 0.001839 0.267346 -0.588273 -0.127686 1.574527 0.866999 0.005422 1.187921 -0.112778 0.033906

    • 卢明冬
      卢明冬
      2020年4月18日 at 上午11:47
      回复

      我这边纯粹按你的数据试了下,没有问题,首页资料页有我的微信,你可以加我微信沟通,评论里写代码不方便。

写下您的评论...