如果列中的值在一组值列表中,则过滤dataframe行

我有一个Pythonpandas数据框rpt

 rpt <class 'pandas.core.frame.DataFrame'> MultiIndex: 47518 entries, ('000002', '20120331') to ('603366', '20091231') Data columns: STK_ID 47518 non-null values STK_Name 47518 non-null values RPT_Date 47518 non-null values sales 47518 non-null values 

我可以像这样筛选库存号为'600809'的行: rpt[rpt['STK_ID'] == '600809']

 <class 'pandas.core.frame.DataFrame'> MultiIndex: 25 entries, ('600809', '20120331') to ('600809', '20060331') Data columns: STK_ID 25 non-null values STK_Name 25 non-null values RPT_Date 25 non-null values sales 25 non-null values 

我想把一些股票的所有行整合在一起,比如['600809','600141','600329'] 。 这意味着我需要这样的语法:

 stk_list = ['600809','600141','600329'] rst = rpt[rpt['STK_ID'] in stk_list] # this does not works in pandas 

既然pandas不接受上述命令,如何达到目标?

使用isin方法。 rpt[rpt['STK_ID'].isin(stk_list)]

如果你有一个完全匹配的列表, isin()是理想的,但是如果你有一个要查找的部分匹配或者子串的列表,你可以使用str.contains方法和正则expression式进行过滤。

例如,如果我们要返回一个DataFrame,其中所有以'600'开头的股票ID后面跟着三个数字:

 >>> rpt[rpt['STK_ID'].str.contains(r'^600[0-9]{3}$')] # ^ means start of string ... STK_ID ... # [0-9]{3} means any three digits ... '600809' ... # $ means end of string ... '600141' ... ... '600329' ... ... ... ... 

现在假设我们有一个我们希望'STK_ID'的值结束的string列表,例如

 endstrings = ['01$', '02$', '05$'] 

我们可以用正则expression式“或”字符连接这些string 并将string传递给str.contains以过滤DataFrame:

 >>> rpt[rpt['STK_ID'].str.contains('|'.join(endstrings)] ... STK_ID ... ... '155905' ... ... '633101' ... ... '210302' ... ... ... ... 

最后, contains可以忽略大小写(通过设置case=False ),允许在指定要匹配的string时更加通用。

例如,

 str.contains('pandas', case=False) 

会匹配PANDASPanDAspaNdAs123等等。

你也可以使用范围:

 b = df[(df['a'] > 1) & (df['a'] < 5)] 

您也可以直接查询您的DataFrame的这些信息。

 rpt.query('STK_ID in (600809,600141,600329)') 

或者类似的search范围:

 rpt.query('60000 < STK_ID < 70000') 

用大pandas切片数据

给定一个像这样的数据框:

  RPT_Date STK_ID STK_Name sales 0 1980-01-01 0 Arthur 0 1 1980-01-02 1 Beate 4 2 1980-01-03 2 Cecil 2 3 1980-01-04 3 Dana 8 4 1980-01-05 4 Eric 4 5 1980-01-06 5 Fidel 5 6 1980-01-07 6 George 4 7 1980-01-08 7 Hans 7 8 1980-01-09 8 Ingrid 7 9 1980-01-10 9 Jones 4 

有多种select或切片数据的方法。

使用.isin

最明显的是.isinfunction。 您可以创build一个掩码,为您提供一系列True / False语句,这些语句可以应用于如下所示的数据框:

 mask = df['STK_ID'].isin([4, 2, 6]) mask 0 False 1 False 2 True 3 False 4 True 5 False 6 True 7 False 8 False 9 False Name: STK_ID, dtype: bool df[mask] RPT_Date STK_ID STK_Name sales 2 1980-01-03 2 Cecil 2 4 1980-01-05 4 Eric 4 6 1980-01-07 6 George 4 

掩蔽是解决问题的临时解决scheme,但在速度和内存方面并不总是performance良好。

与索引

通过将索引设置为STK_ID列,我们可以使用pandas内置切片对象.loc

 df.set_index('STK_ID', inplace=True) RPT_Date STK_Name sales STK_ID 0 1980-01-01 Arthur 0 1 1980-01-02 Beate 4 2 1980-01-03 Cecil 2 3 1980-01-04 Dana 8 4 1980-01-05 Eric 4 5 1980-01-06 Fidel 5 6 1980-01-07 George 4 7 1980-01-08 Hans 7 8 1980-01-09 Ingrid 7 9 1980-01-10 Jones 4 df.loc[[4, 2, 6]] RPT_Date STK_Name sales STK_ID 4 1980-01-05 Eric 4 2 1980-01-03 Cecil 2 6 1980-01-07 George 4 

这是做这个快速的方法,即使索引可能需要一点时间,如果你想做这样的多个查询,它也可以节省时间。

合并dataframe

这也可以通过合并dataframe来完成。 这将适合更多的情况下,你有更多的数据比在这些例子。

 stkid_df = pd.DataFrame({"STK_ID": [4,2,6]}) df.merge(stkid_df, on='STK_ID') STK_ID RPT_Date STK_Name sales 0 2 1980-01-03 Cecil 2 1 4 1980-01-05 Eric 4 2 6 1980-01-07 George 4 

注意

即使有多个具有相同'STK_ID'行,

你可以使用query ,即:

 b = df.query('a > 1 & a < 5') 

你也可以通过使用'query'和@来获得相似的结果:

例如:

 df = pd.DataFrame({'A': [1, 2, 3], 'B': ['a', 'b', 'f']}) df = pd.DataFrame({'A' : [5,6,3,4], 'B' : [1,2,3, 5]}) list_of_values = [3,6] result= df.query("A in @list_of_values") result AB 1 6 2 2 3 3