按日期过滤 Pandas DataFrames

问题描述 投票:0回答:17

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

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

python datetime pandas filtering dataframe
17个回答
479
投票

如果 date 列是索引,则使用 .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')]

请参阅此处了解一般说明

注意:.ix 已弃用。


90
投票

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

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

73
投票

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

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

要使用 datetime 包标准化日期字符串,您可以使用此函数:

import datetime
datetime.datetime.strptime

59
投票

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

df = df[(df['Date'] > "2018-01-01") & (df['Date'] < "2019-07-01")]


38
投票

按日期过滤数据框的最短方法: 假设您的日期列是 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']

33
投票

如果您的日期时间列具有 Pandas 日期时间类型(例如

datetime64[ns]
),为了正确过滤,您需要 pd.Timestamp 对象,例如:

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]

26
投票

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

df['20160101':'20160301']

编辑:虽然很短,但这种风格现在已被弃用(至少从pandas 1.5.3开始),推荐的风格是

df.loc['20160101':'20160301']
(如其他答案)


20
投票

您可以使用 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

查看 pandas 文档中的 DataFrame.query,特别是关于本地变量引用 udsing

@
前缀的提及。在本例中,我们使用本地别名
pd.Timestamp
来引用
ts
,以便能够提供时间戳字符串


13
投票

我还不能写任何评论,所以如果有人会阅读所有评论并达到这个答案,我会写一个答案。

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

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

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


11
投票

因此,在加载 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。希望您会发现这很有用。


7
投票
import pandas as pd

第 1 步:使用 pd.to_datetime()

将日期列转换为 pandas 日期时间
df['date']=pd.to_datetime(df["date"],unit='s')

第2步:以任何预定方式(即2个月)执行过滤

df = df[(df["date"] >"2022-03-01" & df["date"] < "2022-05-03")]

5
投票

您可以通过执行以下操作来选择时间范围:

df.loc['start_date':'end_date']


4
投票

使用怎么样

pyjanitor

它有很酷的功能。

之后

pip install pyjanitor

import janitor

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

4
投票

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

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

返回空。 而

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

返回了预期的数据。


3
投票

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

它允许您使用像 .query(f"{start} < MyDate < {end}") 这样的可读代码,但 .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的回答)


2
投票
# 60 days from today
after_60d = pd.to_datetime('today').date() + datetime.timedelta(days=60)
# filter date col less than 60 days date
df[df['date_col'] < after_60d]

0
投票

--- 或者替代解决方案是使用自动化功能 ---

import pandas as pd

# set current_time
current_time = pd.to_datetime("2024/09/08")

# set function for have time_index_df or have time_column_df
def get_last_two_months(df:pd.DataFrame, current_time, time_col:str=None, has_time_index:bool=False) -> pd.DataFrame:

    # calculate last_time for two months and set date_ranges !
    last_time = current_time + pd.Timedelta(60, "d")
    last_two_months = pd.date_range(current_time, last_time, freq="d").date

    # if dataset has time_index !
    if has_time_index:
        df.index = df.index.astype("datetime64[ns]").date
        return df.loc[df.index.isin(last_two_months)]

    # if dataset has time_column !
    elif time_col:
        df[time_col] = df[time_col].astype("datetime64[ns]").dt.date
        return df[df[time_col].isin(last_two_months)]
© www.soinside.com 2019 - 2024. All rights reserved.