2015-03-31 62 views
61

我从CSV创建一个数据帧如下之间选择数据帧行。有没有办法创建一个只包含特定日期范围内的行的新数据框(或只是覆盖现有的数据框)?两个日期

回答

146

有两种可能的解决方案:

  • 使用布尔面膜,然后用df.loc[mask]
  • 设定日期列作为DatetimeIndex,然后用df[start_date : end_date]

使用布尔掩码

确保df['date']是D型datetime64[ns]一个系列:

df['date'] = pd.to_datetime(df['date']) 

进行布尔面具。 start_dateend_date可以datetime.datetime S, np.datetime64 S,pd.Timestamp S,甚至日期时间字符串:

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

如果你打算做了很多的日期选择的,它可能会更快首先设置 date列作为索引。然后,您可以使用 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]包括start,但不包括end,相反,熊猫df.loc[start_date : end_date]包括两者如果它们在索引中,则结果中的终点。然而,start_dateend_date都不得不在索引中。


另外请注意,pd.read_csv has a parse_dates parameter,你可以用它来解析datedatetime64秒。因此,如果您使用parse_dates,则不需要使用df['date'] = pd.to_datetime(df['date'])

+0

第二警告DatetimeIndex不会出现t o再成真。 – derNincompoop 2017-10-16 17:42:49

+0

@derNincompoop:感谢您的纠正。 – unutbu 2017-10-16 17:57:04

15

我觉得最好的选择将是使用直接检查,而不是使用LOC函数:

df = df[(df['date'] > '2000-6-1') & (df['date'] <= '2000-6-10')] 

这对我的作品。

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

11

您可以使用isin方法上date柱像这样 df[df["date"].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 
1

在情况下,如果你打算做这通常是最好的解决方案将是第一次设置日期列作为将转换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')] 
0

我不喜欢改变df

的选项是检索startend日期的index

import numpy as np 
import pandas as pd 

#Dummy DataFrame 
df = pd.DataFrame(np.random.random((30, 3))) 
df['date'] = pd.date_range('2017-1-1', periods=30, freq='D') 

#Get the index of the start and end dates respectively 
start = df[df['date']=='2017-01-07'].index[0] 
end = df[df['date']=='2017-01-14'].index[0] 

#Show the sliced df (from 2017-01-07 to 2017-01-14) 
df.loc[start:end] 

导致:

 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 
0

您还可以使用between

df[df.some_date.between(start_date, end_date)]