【问题标题】:Filtering Pandas DataFrames on dates按日期过滤 Pandas DataFrame
【发布时间】:2014-05-18 21:26:50
【问题描述】:

我有一个带有“日期”列的 Pandas DataFrame。现在我需要过滤掉 DataFrame 中日期在接下来两个月之外的所有行。本质上,我只需要保留接下来两个月内的行。

实现这一目标的最佳方法是什么?

【问题讨论】:

    标签: python datetime pandas filtering dataframe


    【解决方案1】:

    如果日期列是索引,则使用 .loc 进行基于标签的索引或使用 .iloc 进行位置索引。

    例如:

    df.loc['2014-01-01':'2014-02-01']
    

    在此处查看详细信息http://pandas.pydata.org/pandas-docs/stable/dsintro.html#indexing-selection

    如果该列不是索引,您有两种选择:

    1. 将其设为索引(如果是时间序列数据,则为临时或永久)
    2. df[(df['date'] > '2013-01-01') & (df['date'] < '2013-02-01')]

    一般解释见here

    注意:.ix 已弃用。

    【讨论】:

    • 谢谢,会看的。日期是一个单独的列,而不是我的索引。我可能应该首先提供这些信息。我的问题信息量不大。
    • 您也可以在这里使用querydf.query('20130101 < date < 20130201').
    • 您应该提到示例中的索引过滤器(通过.loc.ix)和列不等效。 df.ix['2014-01-01':'2014-02-01'] 包括2014-02-01df[(df['date'] > '2013-01-01') & (df['date'] < '2013-02-01')] 不包括2013-02-01,它只会匹配到2013-01-31 的行。
    • 此调用现已弃用!
    • 如果不想过滤某个日期范围,而是过滤多个日期时间怎么办?
    【解决方案2】:

    根据我的经验,以前的答案是不正确的,你不能传递一个简单的字符串,需要是一个日期时间对象。所以:

    import datetime 
    df.loc[datetime.date(year=2014,month=1,day=1):datetime.date(year=2014,month=2,day=1)]
    

    【讨论】:

    • 我绝对可以毫无问题地传递一个字符串。
    • ix 索引器已弃用,使用 loc - pandas.pydata.org/pandas-docs/stable/…
    • pandas 会将任何“日期时间”字符串转换为日期时间对象.. 所以它是正确的
    • 我收到以下错误:TypeError: '
    【解决方案3】:

    如果你的日期是通过导入 datetime 包标准化的,你可以简单地使用:

    df[(df['date']>datetime.date(2016,1,1)) & (df['date']<datetime.date(2016,3,1))]  
    

    为了使用 datetime 包标准化你的日期字符串,你可以使用这个函数:

    import datetime
    datetime.datetime.strptime
    

    【讨论】:

    • 推荐使用df[(df['date']&gt;pd.Timestamp(2016,1,1)) &amp; (df['date']&lt;pd.Timestamp(2016,3,1))]
    【解决方案4】:

    如果您已经使用 pd.to_datetime 将字符串转换为日期格式,则可以使用:

    df = df[(df['Date'] &gt; "2018-01-01") &amp; (df['Date'] &lt; "2019-07-01")]

    【讨论】:

      【解决方案5】:

      如果您的日期时间列具有 Pandas 日期时间类型(例如 datetime64[ns]),则为了正确过滤您需要 pd.Timestamp object,例如:

      from datetime import date
      
      import pandas as pd
      
      value_to_check = pd.Timestamp(date.today().year, 1, 1)
      filter_mask = df['date_column'] < value_to_check
      filtered_df = df[filter_mask]
      

      【讨论】:

        【解决方案6】:

        按日期过滤数据框的最短方法: 假设您的日期列是 datetime64[ns]

        类型
        # filter by single day
        df_filtered = df[df['date'].dt.strftime('%Y-%m-%d') == '2014-01-01']
        
        # filter by single month
        df_filtered = df[df['date'].dt.strftime('%Y-%m') == '2014-01']
        
        # filter by single year
        df_filtered = df[df['date'].dt.strftime('%Y') == '2014']
        

        【讨论】:

          【解决方案7】:

          如果日期在索引中,那么只需:

          df['20160101':'20160301']
          

          【讨论】:

            【解决方案8】:

            您可以使用 pd.Timestamp 执行查询和本地引用

            import pandas as pd
            import numpy as np
            
            df = pd.DataFrame()
            ts = pd.Timestamp
            
            df['date'] = np.array(np.arange(10) + datetime.now().timestamp(), dtype='M8[s]')
            
            print(df)
            print(df.query('date > @ts("20190515T071320")')
            

            输出

                             date
            0 2019-05-15 07:13:16
            1 2019-05-15 07:13:17
            2 2019-05-15 07:13:18
            3 2019-05-15 07:13:19
            4 2019-05-15 07:13:20
            5 2019-05-15 07:13:21
            6 2019-05-15 07:13:22
            7 2019-05-15 07:13:23
            8 2019-05-15 07:13:24
            9 2019-05-15 07:13:25
            
            
                             date
            5 2019-05-15 07:13:21
            6 2019-05-15 07:13:22
            7 2019-05-15 07:13:23
            8 2019-05-15 07:13:24
            9 2019-05-15 07:13:25
            

            查看 DataFrame.query 的 pandas 文档,特别是提及引用 udsing @ 前缀的本地变量。在这种情况下,我们使用本地别名 ts 引用 pd.Timestamp 以便能够提供时间戳字符串

            【讨论】:

            • 您能否传递@ts 函数的文档链接?
            • 这里可能不需要pd.TimeStampdf.query('date &gt; 20190515071320') 似乎工作正常。
            【解决方案9】:

            因此,在加载 csv 数据文件时,我们现在需要将日期列设置为索引,如下所示,以便根据日期范围过滤数据。现在已弃用的方法不需要此方法:pd.DataFrame.from_csv()。

            如果您只想显示从一月到二月的两个月的数据,例如2020-01-01 至 2020-02-29,您可以这样做:

            import pandas as pd
            mydata = pd.read_csv('mydata.csv',index_col='date') # or its index number, e.g. index_col=[0]
            mydata['2020-01-01':'2020-02-29'] # will pull all the columns
            #if just need one column, e.g. Cost, can be done:
            mydata['2020-01-01':'2020-02-29','Cost'] 
            

            这已经过测试,适用于 Python 3.7。希望你会发现这很有用。

            【讨论】:

            • index_col 必须是 string 而不是列表。 mydata = pd.read_csv('mydata.csv',index_col='date')
            【解决方案10】:

            我还不允许写任何 cmets,所以我会写一个答案,如果有人会阅读所有这些并达到这个答案。

            如果数据集的索引是日期时间,并且您希望仅按(例如)月份过滤,您可以执行以下操作:

            df.loc[df.index.month == 3]
            

            这将在 3 月之前为您过滤数据集。

            【讨论】:

            • 我觉得有一个小错字,应该是df.loc[df.index.month == 3]
            【解决方案11】:

            pyjanitor怎么样

            它有很酷的功能。

            pip install pyjanitor之后

            import janitor
            
            df_filtered = df.filter_date(your_date_column_name, start_date, end_date)
            

            【讨论】:

            • ValueError: Series 的真值不明确。使用 a.empty、a.bool()、a.item()、a.any() 或 a.all()。
            【解决方案12】:

            您可以通过以下方式选择时间范围:df.loc['start_date':'end_date']

            【讨论】:

              【解决方案13】:

              如果您想使用 .query() 方法,另一种解决方案。

              它允许你使用像 .query(f"{start} 这样的可读代码来进行权衡,即 .query() 解析字符串和列值必须是 pandas 日期格式(这样 .query() 也可以理解)

              df = pd.DataFrame({
                   'MyValue': [1,2,3],
                   'MyDate': pd.to_datetime(['2021-01-01','2021-01-02','2021-01-03'])
              })
              start = datetime.date(2021,1,1).strftime('%Y%m%d')
              end = datetime.date(2021,1,3).strftime('%Y%m%d')
              df.query(f"{start} < MyDate < {end}")
              

              (根据@Phillip Cloud 的评论,@Retozi 的回答)

              【讨论】:

                【解决方案14】:

                在 pandas 1.1.3 版中,我遇到了基于 python 日期时间的索引按降序排列的情况。在这种情况下

                df.loc['2021-08-01':'2021-08-31']
                

                返回空。而

                df.loc['2021-08-31':'2021-08-01']
                

                返回了预期的数据。

                【讨论】:

                  猜你喜欢
                  • 1970-01-01
                  • 1970-01-01
                  • 1970-01-01
                  • 2016-08-21
                  • 2017-09-06
                  • 2019-04-29
                  相关资源
                  最近更新 更多