Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/python/345.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Python 选择两个日期之间的数据帧行_Python_Pandas - Fatal编程技术网

Python 选择两个日期之间的数据帧行

Python 选择两个日期之间的数据帧行,python,pandas,Python,Pandas,我正在从csv创建数据帧,如下所示: stock = pd.read_csv('data_in/' + filename + '.csv', skipinitialspace=True) DataFrame有一个日期列。有没有办法创建一个新的数据框,或者只覆盖现有的数据框,该数据框只包含日期值在指定日期范围内或在两个指定日期值之间的行?有两种可能的解决方案: 使用布尔掩码,然后使用df.loc[mask] 将date列设置为DatetimeIndex,然后使用df[开始日期:结束日期] 使用布

我正在从csv创建数据帧,如下所示:

stock = pd.read_csv('data_in/' + filename + '.csv', skipinitialspace=True)

DataFrame有一个日期列。有没有办法创建一个新的数据框,或者只覆盖现有的数据框,该数据框只包含日期值在指定日期范围内或在两个指定日期值之间的行?

有两种可能的解决方案:

使用布尔掩码,然后使用df.loc[mask] 将date列设置为DatetimeIndex,然后使用df[开始日期:结束日期] 使用布尔掩码:

确保df['date']是数据类型为datetime64[ns]的系列:

制作一个布尔掩码。开始日期和结束日期可以是datetime.datetimes, np.datetime64s、pd.Timestamps甚至datetime字符串:

#greater than the start date and smaller than the end date
mask = (df['date'] > start_date) & (df['date'] <= end_date)
或重新分配给df

比如说,

将numpy作为np导入 作为pd进口熊猫 df=pd.DataFramenp.random.random200,3 df['date']=pd.date_范围'2000-1-1',周期=200,频率=D'
mask=df['date']>'2000-6-1'&df['date']我觉得最好的选择是使用直接检查,而不是使用loc功能:

df = df[(df['date'] > '2000-6-1') & (df['date'] <= '2000-6-10')]
它对我有用

带切片的loc函数的主要问题是,限制应出现在实际值中,否则将导致KeyError。

您可以在日期列上使用isin方法,如下所示 df[df[date].isinpd.date\u range开始日期,结束日期]

注意:这只适用于问题提出的日期,而不适用于时间戳

例如:

           0         1         2       date
14  0.960974  0.144271  0.839593 2017-01-15
15  0.814376  0.723757  0.047840 2017-01-16
16  0.911854  0.123130  0.120995 2017-01-17
17  0.505804  0.416935  0.928514 2017-01-18
18  0.204869  0.708258  0.170792 2017-01-19
19  0.014389  0.214510  0.045201 2017-01-20

保持解决方案的简单性和pythonic性,我建议您试试这个

如果要经常这样做,最好的解决方案是首先将date列设置为索引,这将转换DateTimeIndex中的列,并使用以下条件对任何日期范围进行切片

import pandas as pd

data_frame = data_frame.set_index('date')

df = data_frame[(data_frame.index > '2017-08-10') & (data_frame.index <= '2017-08-15')]
我宁愿不改变df

一个选项是检索开始日期和结束日期的索引:

其结果是:

     0   1   2       date
6  0.5 0.8 0.8 2017-01-07
7  0.0 0.7 0.3 2017-01-08
8  0.8 0.9 0.0 2017-01-09
9  0.0 0.2 1.0 2017-01-10
10 0.6 0.1 0.9 2017-01-11
11 0.5 0.3 0.9 2017-01-12
12 0.5 0.4 0.3 2017-01-13
13 0.4 0.9 0.9 2017-01-14
您还可以在以下两者之间使用:

通过我对pandas版本0.22.0的测试,您现在只需使用between,就可以用可读性更强的代码更轻松地回答这个问题

假设您想了解2018年11月27日至2019年1月15日之间的日期:

# use the between statement to get a boolean mask
df['dates'].between('2018-11-27','2019-01-15', inclusive=False)

0    False
1    False
2    False
3    False
4    False

# you can pass this boolean mask straight to loc
df.loc[df['dates'].between('2018-11-27','2019-01-15', inclusive=False)]

    dates
331 2018-11-28
332 2018-11-29
333 2018-11-30
334 2018-12-01
335 2018-12-02
请注意包含性参数。当你想明确你的范围时,这非常有用。请注意,当设置为True时,我们还将返回2018年11月27日:

df.loc[df['dates'].between('2018-11-27','2019-01-15', inclusive=True)]

    dates
330 2018-11-27
331 2018-11-28
332 2018-11-29
333 2018-11-30
334 2018-12-01
此方法也比前面提到的isin方法快:

但是,只有在已创建掩码的情况下,它才不会比unutbu提供的当前接受答案快。但是,如果掩码是动态的,需要反复重新分配,那么我的方法可能更有效:

# already create the mask THEN time the function

start_date = dt.datetime(2018,11,27)
end_date = dt.datetime(2019,1,15)
mask = (df['dates'] > start_date) & (df['dates'] <= end_date)

%%timeit -n 5
df.loc[mask]
191 µs ± 28.5 µs per loop (mean ± std. dev. of 7 runs, 5 loops each)

另一个选择,如何实现这一点,是通过使用方法。让我向您展示以下名为df的数据帧的示例

作为参数,请使用如下筛选条件:

>>> start_date, end_date = '2020-01-02', '2020-01-04'
>>> print(df.query('date >= @start_date and date <= @end_date'))
      col_1       date
1  0.244104 2020-01-02
2  0.374775 2020-01-03
3  0.510053 2020-01-04
如果不希望包括边界,只需更改如下条件:

>>> print(df.query('date > @start_date and date < @end_date'))
      col_1       date
2  0.374775 2020-01-03

您可以使用pd.date\u范围和时间戳来完成。 假设您已使用parse_dates选项读取了带有日期列的csv文件:

df = pd.read_csv('my_file.csv', parse_dates=['my_date_col'])
然后可以定义日期范围索引:

rge = pd.date_range(end='15/6/2020', periods=2)
然后通过地图按日期过滤您的值:

df.loc[df['my_date_col'].map(lambda row: row.date() in rge)]
灵感来自联合国大学

print(df.dtypes)                                 #Make sure the format is 'object'. Rerunning this after index will not show values.
columnName = 'YourColumnName'
df[columnName+'index'] = df[columnName]          #Create a new column for index
df.set_index(columnName+'index', inplace=True)   #To build index on the timestamp/dates
df.loc['2020-09-03 01:00':'2020-09-06']          #Select range from the index. This is your new Dataframe.

还要检查时间:奇怪的是,@AntonTarasenko不适用于日期时间,而只适用于时间。我花了一段时间才意识到这一区别。这就是我最后咨询这个帖子的原因。将日期列设置为索引效果很好,但从我看到的文档中不清楚是否可以这样做。谢谢。@FaheemMitha:我在上面添加了部分字符串索引。可能不太清楚的是,索引必须显式创建。在没有显式创建索引的情况下,受限范围返回一个空集,而不是一个错误。在df=df.set_index['date']步骤之后,我发现索引也需要通过df.sort_indexinplace=True,ascending=True进行排序,否则您可以从df.loc['2000-6-1':'2000-6-10']获得不完整甚至空的数据帧结果。如果你使用升序=False,那根本不起作用,即使你用df.loc来反转它,['2000-6-10':'2000-6-1']如果你想保留'date'列,同时仍然给数据帧的索引赋值,你可以这样做df.index=df['date'],我认为通过loc进行切片是很好的。在我看来,正如unutbu所说,无论是开始日期还是结束日期都不必在索引中。如何将日期筛选为当前日期之前的14天。。如果今天的日期是2019-01-15。。。我需要2019-01-01到2019-01-15的数据,简单而优雅。谢谢Christin,这就是我想要做的。为我工作,谢谢你。在2021年帮助了我
# use the between statement to get a boolean mask
df['dates'].between('2018-11-27','2019-01-15', inclusive=False)

0    False
1    False
2    False
3    False
4    False

# you can pass this boolean mask straight to loc
df.loc[df['dates'].between('2018-11-27','2019-01-15', inclusive=False)]

    dates
331 2018-11-28
332 2018-11-29
333 2018-11-30
334 2018-12-01
335 2018-12-02
df.loc[df['dates'].between('2018-11-27','2019-01-15', inclusive=True)]

    dates
330 2018-11-27
331 2018-11-28
332 2018-11-29
333 2018-11-30
334 2018-12-01
%%timeit -n 5
df.loc[df['dates'].between('2018-11-27','2019-01-15', inclusive=True)]
868 µs ± 164 µs per loop (mean ± std. dev. of 7 runs, 5 loops each)


%%timeit -n 5

df.loc[df['dates'].isin(pd.date_range('2018-01-01','2019-01-01'))]
1.53 ms ± 305 µs per loop (mean ± std. dev. of 7 runs, 5 loops each)
# already create the mask THEN time the function

start_date = dt.datetime(2018,11,27)
end_date = dt.datetime(2019,1,15)
mask = (df['dates'] > start_date) & (df['dates'] <= end_date)

%%timeit -n 5
df.loc[mask]
191 µs ± 28.5 µs per loop (mean ± std. dev. of 7 runs, 5 loops each)
>>> df = pd.DataFrame(np.random.random((5, 1)), columns=['col_1'])
>>> df['date'] = pd.date_range('2020-1-1', periods=5, freq='D')
>>> print(df)
      col_1       date
0  0.015198 2020-01-01
1  0.638600 2020-01-02
2  0.348485 2020-01-03
3  0.247583 2020-01-04
4  0.581835 2020-01-05
>>> start_date, end_date = '2020-01-02', '2020-01-04'
>>> print(df.query('date >= @start_date and date <= @end_date'))
      col_1       date
1  0.244104 2020-01-02
2  0.374775 2020-01-03
3  0.510053 2020-01-04
>>> print(df.query('date > @start_date and date < @end_date'))
      col_1       date
2  0.374775 2020-01-03
df = pd.read_csv('my_file.csv', parse_dates=['my_date_col'])
rge = pd.date_range(end='15/6/2020', periods=2)
df.loc[df['my_date_col'].map(lambda row: row.date() in rge)]
print(df.dtypes)                                 #Make sure the format is 'object'. Rerunning this after index will not show values.
columnName = 'YourColumnName'
df[columnName+'index'] = df[columnName]          #Create a new column for index
df.set_index(columnName+'index', inplace=True)   #To build index on the timestamp/dates
df.loc['2020-09-03 01:00':'2020-09-06']          #Select range from the index. This is your new Dataframe.