我正在从csv创建一个DataFrame,如下所示:
stock = pd.read_csv('data_in/' + filename + '.csv', skipinitialspace=True)
DataFrame有一个日期列。是否有一种方法可以创建一个新的DataFrame(或者只是覆盖现有的DataFrame),它只包含日期值落在指定日期范围内或两个指定日期值之间的行?
我正在从csv创建一个DataFrame,如下所示:
stock = pd.read_csv('data_in/' + filename + '.csv', skipinitialspace=True)
DataFrame有一个日期列。是否有一种方法可以创建一个新的DataFrame(或者只是覆盖现有的DataFrame),它只包含日期值落在指定日期范围内或两个指定日期值之间的行?
当前回答
为了保持解决方案的简单和python性,我建议您尝试一下。
在这种情况下,如果你要经常这样做,最好的解决方案是首先将日期列设置为索引,这将转换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')]
其他回答
另一种方法是使用pandas.DataFrame.query()方法。让我给你们看一个关于下面数据帧的例子,叫做df。
>>> 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
您可以像这样在日期列上使用isin方法 df (df .isin (pd(“日期”)。date_range (start_date end_date)))
注意:这只适用于日期(正如问题所要求的),而不适用于时间戳。
例子:
import numpy as np
import pandas as pd
# Make a DataFrame with dates and random numbers
df = pd.DataFrame(np.random.random((30, 3)))
df['date'] = pd.date_range('2017-1-1', periods=30, freq='D')
# Select the rows between two dates
in_range_df = df[df["date"].isin(pd.date_range("2017-01-15", "2017-01-20"))]
print(in_range_df) # print result
这给了
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
你也可以用between:
df[df.some_date.between(start_date, end_date)]
我觉得最好的选择是使用直接检查,而不是使用loc函数:
df = df[(df['date'] > '2000-6-1') & (df['date'] <= '2000-6-10')]
这对我很管用。
使用切片的loc函数的主要问题是限制应该出现在实际值中,否则将导致KeyError。
有两种可能的解决方案:
使用布尔掩码,然后使用df.loc[掩码] 将日期列设置为DatetimeIndex,然后使用df[start_date: end_date]
使用布尔掩码:
确保df['date']是dtype datetime64[ns]的Series:
df['date'] = pd.to_datetime(df['date'])
制作一个布尔掩码。Start_date和end_date可以是datetime.datetimes, np。datetime64s pd。时间戳,甚至是datetime字符串:
#greater than the start date and smaller than the end date
mask = (df['date'] > start_date) & (df['date'] <= end_date)
选择子数据帧:
df.loc[mask]
或者重新赋值给df
df = df.loc[mask]
例如,
import numpy as np
import pandas as pd
df = pd.DataFrame(np.random.random((200,3)))
df['date'] = pd.date_range('2000-1-1', periods=200, freq='D')
mask = (df['date'] > '2000-6-1') & (df['date'] <= '2000-6-10')
print(df.loc[mask])
收益率
0 1 2 date
153 0.208875 0.727656 0.037787 2000-06-02
154 0.750800 0.776498 0.237716 2000-06-03
155 0.812008 0.127338 0.397240 2000-06-04
156 0.639937 0.207359 0.533527 2000-06-05
157 0.416998 0.845658 0.872826 2000-06-06
158 0.440069 0.338690 0.847545 2000-06-07
159 0.202354 0.624833 0.740254 2000-06-08
160 0.465746 0.080888 0.155452 2000-06-09
161 0.858232 0.190321 0.432574 2000-06-10
使用DatetimeIndex:
如果要按日期进行大量选择,则设置 首先将日期列作为索引。然后可以使用按日期选择行 df.loc [start_date: end_date]。
import numpy as np
import pandas as pd
df = pd.DataFrame(np.random.random((200,3)))
df['date'] = pd.date_range('2000-1-1', periods=200, freq='D')
df = df.set_index(['date'])
print(df.loc['2000-6-1':'2000-6-10'])
收益率
0 1 2
date
2000-06-01 0.040457 0.326594 0.492136 # <- includes start_date
2000-06-02 0.279323 0.877446 0.464523
2000-06-03 0.328068 0.837669 0.608559
2000-06-04 0.107959 0.678297 0.517435
2000-06-05 0.131555 0.418380 0.025725
2000-06-06 0.999961 0.619517 0.206108
2000-06-07 0.129270 0.024533 0.154769
2000-06-08 0.441010 0.741781 0.470402
2000-06-09 0.682101 0.375660 0.009916
2000-06-10 0.754488 0.352293 0.339337
而Python列表索引,例如seq[start:end]包括开始,但不包括结束,相比之下,Pandas df。Loc [start_date: end_date]在结果中包含两个端点,如果它们在索引中。但是,start_date和end_date都不能在索引中。
还要注意pd。Read_csv有一个parse_dates参数,您可以使用该参数将日期列解析为datetime64s。因此,如果使用parse_dates,则不需要使用df['date'] = pd.to_datetime(df['date'])。