Skip to main content
 首页 » 编程设计

python之使用正则表达式在 Pandas 中过滤

2024年10月01日8mengfanrong

我使用 pandas 和 python 在 excel 中做一些工作。我有这样的东西。

  ID         Actual Date 
738564     01/21/2016 
274628     02/12/2016 
571749     03/30/2016 
718563     10/01/2016 
984739     11/30/2016 
938511     12/24/2016 
103216     07/16/2014 
446754     08/06/2015 
135654     02/01/2017 
135614     01/16/2017 
133346     01/16/2011 
234682        N/A 
238756       (none) 

所以我需要按日期过滤,但我只需要过滤 2016 年 11 月之前的年份日期(所以我需要过滤 2014 年、2015 年以及 2016 年 1 月和 10 月之间的日期)。所以基本上在过滤器之后我会有这样的东西

      ID       Actual Date 
   738564   01/21/2016 
   274628   02/12/2016 
   571749   03/30/2016 
   718563   10/01/2016 
   103216   07/16/2014 
   446754   08/06/2015 
   133346   01/16/2011 
   234682        N/A 
   238756       (none) 

我为此使用的代码是:

    regex = r"[0-9]{2}/[0-9]{2}/2016" 
df = pd.read_csv("Request.csv", keep_default_na=False) 
df1 = df.loc[(df["Actual Date"].str.contains(r'[0-9]{2}/[0-9]{2}/2016') & 
             (df["Actual Date"].str.contains("2015")) &  
             (df["Actual Date"].str.contains("2014")) & 
             (df["Actual Date"].str.contains("2011")) & 
             (df["Actual Date"].str.contains("(None)")) & 
             (df["Actual Date"].str.contains("N/A"))))]                  

但是当我运行代码时,我只收到 2011 年、2014 年和 2015 年的数据。正则表达式不适用于 2016 年的日期。 非常感谢您的帮助,对于糟糕的英语表示抱歉

请您参考如下方法:

RegEx 是非常强大的工具,但在这种情况下有更好的方法:

In [180]: df 
Out[180]: 
        ID  ActualDate 
0   738564  01/21/2016 
1   274628  02/12/2016 
2   571749  03/30/2016 
3   718563  10/01/2016 
4   984739  11/30/2016 
5   938511  12/24/2016 
6   103216  07/16/2014 
7   446754  08/06/2015 
8   135654  02/01/2017 
9   135614  01/16/2017 
10  133346  01/16/2011 
11  234682         NaN 
12  238756      (none) 

让我们把它转换成datetime dtype:

In [181]: df['ActualDate'] = pd.to_datetime(df['ActualDate'], errors='coerce') 
 
In [182]: df 
Out[182]: 
        ID ActualDate 
0   738564 2016-01-21 
1   274628 2016-02-12 
2   571749 2016-03-30 
3   718563 2016-10-01 
4   984739 2016-11-30 
5   938511 2016-12-24 
6   103216 2014-07-16 
7   446754 2015-08-06 
8   135654 2017-02-01 
9   135614 2017-01-16 
10  133346 2011-01-16 
11  234682        NaT 
12  238756        NaT 

使用 boolean indexing 过滤:

In [184]: df[(df['ActualDate'] < '2016-11-01') | df['ActualDate'].isnull()] 
Out[184]: 
        ID ActualDate 
0   738564 2016-01-21 
1   274628 2016-02-12 
2   571749 2016-03-30 
3   718563 2016-10-01 
6   103216 2014-07-16 
7   446754 2015-08-06 
10  133346 2011-01-16 
11  234682        NaT 
12  238756        NaT 

使用 .query() 过滤方法:

In [186]: df.query("ActualDate < '2016-11-01' or ActualDate != ActualDate") 
Out[186]: 
        ID ActualDate 
0   738564 2016-01-21 
1   274628 2016-02-12 
2   571749 2016-03-30 
3   718563 2016-10-01 
6   103216 2014-07-16 
7   446754 2015-08-06 
10  133346 2011-01-16 
11  234682        NaT 
12  238756        NaT 

更新:如果您想在字符串数据类型中保留原始日期:

In [190]: df 
Out[190]: 
        ID Actual Date 
0   738564  01/21/2016 
1   274628  02/12/2016 
2   571749  03/30/2016 
3   718563  10/01/2016 
4   984739  11/30/2016 
5   938511  12/24/2016 
6   103216  07/16/2014 
7   446754  08/06/2015 
8   135654  02/01/2017 
9   135614  01/16/2017 
10  133346  01/16/2011 
11  234682         NaN 
12  238756      (none) 

首先添加一个新的datetime列:

In [191]: df['Date'] = pd.to_datetime(df['Actual Date'], errors='coerce') 
 
In [192]: df 
Out[192]: 
        ID Actual Date       Date 
0   738564  01/21/2016 2016-01-21 
1   274628  02/12/2016 2016-02-12 
2   571749  03/30/2016 2016-03-30 
3   718563  10/01/2016 2016-10-01 
4   984739  11/30/2016 2016-11-30 
5   938511  12/24/2016 2016-12-24 
6   103216  07/16/2014 2014-07-16 
7   446754  08/06/2015 2015-08-06 
8   135654  02/01/2017 2017-02-01 
9   135614  01/16/2017 2017-01-16 
10  133346  01/16/2011 2011-01-16 
11  234682         NaN        NaT 
12  238756      (none)        NaT 

过滤:

In [194]: df.drop('Date', 1).loc[(df['Date'] < '2016-11-01') | df['Date'].isnull()] 
Out[194]: 
        ID Actual Date 
0   738564  01/21/2016 
1   274628  02/12/2016 
2   571749  03/30/2016 
3   718563  10/01/2016 
6   103216  07/16/2014 
7   446754  08/06/2015 
10  133346  01/16/2011 
11  234682         NaN 
12  238756      (none) 
 
 
In [196]: df.query("Date < '2016-11-01' or Date != Date").drop('Date', 1) 
Out[196]: 
        ID Actual Date 
0   738564  01/21/2016 
1   274628  02/12/2016 
2   571749  03/30/2016 
3   718563  10/01/2016 
6   103216  07/16/2014 
7   446754  08/06/2015 
10  133346  01/16/2011 
11  234682         NaN 
12  238756      (none)