【问题标题】:Conditions in a new column df with Numpy and Timedelta具有 Numpy 和 Timedelta 的新列 df 中的条件
【发布时间】:2018-04-21 05:32:32
【问题描述】:

我正在根据 df 的 2 列,inc_cr_date_day 和 inc_cr_date 创建一个新的 df 列 ['inc_cr_date_adjusted'],但下面的代码没有按预期工作。不会给出错误,但它不像条件所定义的那样工作,因为只有周六和周日工作的条件。包含小时和时间的条件不起作用,因为天数没有汇总(Timedelta('1 days'). 另一个问题是大多数日期应该假定最后一行代码“df['inc_cr_date'])”并且根本不改变,但这也没有出现。

我的条件基于 inc_cr_date 列中可见的星期几和小时和分钟。小时和分钟是 9:30 和 18:30,使用 & 分隔。

代码是:

df['inc_cr_date_day'] = df['inc_cr_date'].dt.weekday_name

df['inc_cr_date_adjusted'] = np.select([(df['inc_cr_date_day'] == 'Saturday'),#condition working
                              (df['inc_cr_date_day'] == 'Sunday'),#condition working
                              ((df['inc_cr_date_day'] == 'Monday')& (df['inc_cr_date'].dt.hour > 18 ) & df['inc_cr_date'].dt.minute > 30),
                              ((df['inc_cr_date_day'] == 'Monday')& (df['inc_cr_date'].dt.hour < 9 ) & df['inc_cr_date'].dt.minute < 30),
                              ((df['inc_cr_date_day'] == 'Tuesday')& (df['inc_cr_date'].dt.hour > 18 ) & df['inc_cr_date'].dt.minute > 30),
                              ((df['inc_cr_date_day'] == 'Tuesday')& (df['inc_cr_date'].dt.hour < 9 ) & df['inc_cr_date'].dt.minute < 30),
                              ((df['inc_cr_date_day'] == 'Wednesday')& (df['inc_cr_date'].dt.hour > 18 ) & df['inc_cr_date'].dt.minute > 30),
                              ((df['inc_cr_date_day'] == 'Wednesday')& (df['inc_cr_date'].dt.hour < 9 ) & df['inc_cr_date'].dt.minute < 30),
                              ((df['inc_cr_date_day'] == 'Thursday')& (df['inc_cr_date'].dt.hour > 18 ) & df['inc_cr_date'].dt.minute > 30),
                              ((df['inc_cr_date_day'] == 'Thursday')& (df['inc_cr_date'].dt.hour < 9 ) & df['inc_cr_date'].dt.minute < 30),
                              ((df['inc_cr_date_day'] == 'Friday')& (df['inc_cr_date'].dt.hour > 18 ) & df['inc_cr_date'].dt.minute > 30),
                              ((df['inc_cr_date_day'] == 'Friday')& (df['inc_cr_date'].dt.hour < 9 ) & df['inc_cr_date'].dt.minute < 30)],


                           [(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('1 days')).dt.normalize() + pd.Timedelta('9 Hours 30 Minutes'),
                            (df['inc_cr_date']+pd.Timedelta('0 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('0 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('0 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('0 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']+pd.Timedelta('0 days')).dt.normalize() + pd.Timedelta('9 Hours 30 Minutes')],

                           df['inc_cr_date'])

输出(那是错误的):

inc_cr_date,inc_cr_date_day,inc_cr_date_adjusted
2017-10-26 21:59:28.075,Thursday,2017-10-26 09:30:00.000 #nok, adjusted should be 2017-10-27 and not 2017-10-26.
2017-10-21 16:49:58.722,Saturday,2017-10-23 09:30:00.000 #ok
2017-10-11 09:30:05.258,Wednesday,2017-10-11 09:30:00.000 #nok, in such situation the adjusted date should be same as inc_cr_date

非常感谢您的意见。

【问题讨论】:

  • 对于这样的操作,我希望你去 binning usinig pd.cut。可能条件有些模棱两可。
  • 我找了一个多小时,找不到什么问题
  • 我已经优化了你的代码看看。 :)

标签: python pandas numpy time timedelta


【解决方案1】:

作为程序员,我们应该尽量减少重复次数(遵循 DRY 原则)。我们可以利用.isin 来获得您想要的结果,即

#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'])

输出:

inc_cr_date inc_cr_date_day inc_cr_date_adjusted 0 2017-10-26 21:59:28.075 星期四 2017-10-27 09:30:00.000 1 2017-10-21 16:49:58.722 星期六 2017-10-23 09:30:00.000 2 2017-10-11 09:30:05.258 星期三 2017-10-11 09:30:05.258

通常,由于多个匹配项,许多条件会产生歧义。希望上面的代码可以帮助您获得所需的结果。当我查看您的代码时,条件的优先级也可能很重要,因此请尝试将括号也放在结束条件中,即

((df['inc_cr_date_day'] == 'Monday')& (df['inc_cr_date'].dt.hour > 18 ) & (df['inc_cr_date'].dt.minute > 30)) 

【讨论】:

  • 刚刚运行它,例如日期“2017-10-26 21:46:37.323”和“2017-10-26 21:29:07.116”提供不同的结果:“2017-10- 27 09:30:00.000”和“2017-10-26 21:29:07.116”。当它们应该具有相同的->“2017-10-27 09:30:00.000”。也许是因为小时和分钟的条件看起来不是 HH:MM 而是单独的条件?!
  • 但是你的代码提供了比以前更正确的结果,这是肯定的
  • 但定义的条件另有说明。也许2017-10-26 21:29:07.116 不满足任何条件。小时大于 18,但分钟小于 30。您可以使用上述方法来获得结果。我有我的作业要写。所以你可以从这里采取进一步的行动。祝你有美好的一天。如果解决方案有帮助,请不要忘记投票。 :)
  • 我会的。非常感谢您的支持。我会努力的。
  • 不可能将 18:30 放在一个条件中以避免这种歧义?
猜你喜欢
  • 2022-01-05
  • 2022-01-02
  • 1970-01-01
  • 2021-01-04
  • 1970-01-01
  • 2023-03-24
  • 2021-01-14
  • 1970-01-01
  • 2021-12-20
相关资源
最近更新 更多