将timedelta与python中的dt.time进行比较

时间:2017-11-09 10:40:24

标签: python datetime timedelta

我有一个名为df['inc_cr_date']的大熊猫系列,其格式为2017-10-27 08:00:26.808

我想比较此列的日期和小时是否高于18:30。问题是如果我使用下面的代码:

#All the condtions can be reduced to one mask and result 
days_one = ['Monday','Tuesday','Wednesday','Thursday']
days_two = days_one + ['Friday']

# Returns a boolean mask 
m1 = df['inc_cr_date_day'].isin(days_one) & (df['inc_cr_date'].dt.hour > 18 ) & (df['inc_cr_date'].dt.minute > 30)
m2 = df['inc_cr_date_day'].isin(days_two) & (df['inc_cr_date'].dt.hour < 9 ) & (df['inc_cr_date'].dt.minute < 30)

# Repeated result can be stored in one variable 
r1 = (df['inc_cr_date']+pd.Timedelta('1 days')).dt.normalize() + pd.Timedelta('9 Hours 30 Minutes')
r2 = (df['inc_cr_date']+pd.Timedelta('0 days')).dt.normalize() + pd.Timedelta('9 Hours 30 Minutes')


df['inc_cr_date_adjusted'] = np.select([
                          m1, m2,      
                          (df['inc_cr_date_day'] == 'Saturday'),
                          (df['inc_cr_date_day'] == 'Sunday'),
                          ((df['inc_cr_date_day'] == 'Friday')& (df['inc_cr_date'].dt.hour > 18 ) & df['inc_cr_date'].dt.minute > 30),
                          ],
                          [r1, r2,
                          (df['inc_cr_date']+pd.Timedelta('2 days')).dt.normalize() + pd.Timedelta('9 Hours 30 Minutes'),
                          (df['inc_cr_date']+pd.Timedelta('1 days')).dt.normalize() + pd.Timedelta('9 Hours 30 Minutes'),                           
                          (df['inc_cr_date']+pd.Timedelta('3 days')).dt.normalize() + pd.Timedelta('9 Hours 30 Minutes')
                          ],
                          df['inc_cr_date'])

这会让我产生模棱两可的结果,因为第一个条件可能是真的,但第二个条件不可能。如何将[&#39; inc_cr_date&#39;]列与18:30进行比较,而不是将分钟和小时分开?

我还尝试使用 pandas.DataFrame.between_time ,如下所示:

start = datetime.time(18,30,0)
end = datetime.time(23,59,0)

df['inc_cr_date'].between_time(start, end) )

但得到错误:

TypeError: Index must be DatetimeIndex

即使我这样做:

df['inc_cr_date'] = pd.DatetimeIndex(df['inc_cr_date'])

Dataframe如下所示:

  inc_cr_date                  inc_cr_date_day       
0 2017-10-26 21:59:28.075      Thursday 2017-10-27   
1 2017-10-21 16:49:58.722      Saturday 2017-10-23   
2 2017-10-11 09:30:05.258      Wednesday 2017-10-11   

输出应该是:

  inc_cr_date                  inc_cr_date_day        inc_cr_date_adjusted
0 2017-10-26 21:20:28.075      Thursday 2017-10-27    09:30:00.000
1 2017-10-21 16:49:58.722      Saturday 2017-10-23    09:30:00.000
2 2017-10-11 09:30:05.258      Wednesday 2017-10-11   09:30:05.258

请指教。感谢。

1 个答案:

答案 0 :(得分:1)

这个怎么样?

df['timeFlag'] = df['inc_cr_date'].apply(lambda x: 1 if x.time() > datetime.time(18, 30, 0) else 0)

在您的示例中,您可以更改以下行:

# Returns a boolean mask 
m1 = df['inc_cr_date_day'].isin(days_one) & (df['inc_cr_date'].dt.hour > 18 ) & (df['inc_cr_date'].dt.minute > 30)
m2 = df['inc_cr_date_day'].isin(days_two) & (df['inc_cr_date'].dt.hour < 9 ) & (df['inc_cr_date'].dt.minute < 30)

为:

# Returns a boolean mask 
m1 = df['inc_cr_date_day'].isin(days_one) & (df['inc_cr_date'].apply(lambda x: 1 if x.time() > datetime.time(18, 30,0) else 0))
m2 = df['inc_cr_date_day'].isin(days_two) & (df['inc_cr_date'].apply(lambda x: 1 if x.time() > datetime.time(18, 30,0) else 0))