Python pandas计算pandas dataframe

时间:2017-12-01 12:15:17

标签: python pandas numpy

周一至周五上午7点到下午5点我的工作时间。我想计算2列开始日期和结束日期的工作日和小时数。

  

Sno start date      end date
1   4/6/2017 23:18  6/6/2017 21:23
2   4/6/2017 16:40  5/6/2017 2:52
3   5/6/2017 0:10   5/6/2017 4:10
4   5/6/2017 0:37   5/6/2017 7:16
5   5/6/2017 2:02   5/6/2017 10:48
  

Sno start date      end date        Bus Days    Bus hours
1   4/6/2017 23:18  6/6/2017 21:23  1           10:00
2   4/6/2017 16:40  5/6/2017 2:52   0           0:20
3   5/6/2017 0:10   5/6/2017 4:10   0           0
4   5/6/2017 0:37   5/6/2017 7:16   0           0:16
5   5/6/2017 2:02   5/6/2017 10:48  0           3:48

我尝试过以下但有几个错误

from BusinessHours import BusinessHours as bh
df['bhours'] = (bh(df['start date'] , df['end date'] , worktiming=[7 , 17] , weekends=[6,7]).gethours()).astype('timedelta64[D]')

AttributeError: 'Series' object has no attribute 'days'

然后我尝试了另一种解决方案

df['bhours'] = len(pd.bdate_range(df['start date'] , df['end date'])).astype('timedelta64[D]')
TypeError: Cannot convert input [0       2017-04-06 18:52:00

df['bdays'] = (np.busday_count(df['start date'] , df['end date'])).astype('timedelta64[D]')
TypeError: Iterator operand 0 dtype could not be cast from dtype('<M8[ns]') to dtype('<M8[D]') according to the rule 'safe'

请帮助解决此问题。

1 个答案:

答案 0 :(得分:0)

我写了这个方法,因为我发现营业时间包有语法错误。它应该工作正常。

import pandas as pd 
import datetime
import numpy as np

df = pd.read_excel("/home/yasin/Documents/SametimeFileTransfers/final.xlsx")

df['sys_created_on'] = pd.to_datetime(df['sys_created_on'] )
df['resolved_at'] = pd.to_datetime(df['resolved_at'])

x = pd.to_datetime('2017-06-15 17:39')
y = pd.to_datetime('2017-06-15 18:00')

weekend = [6 ,7] # --> This is just for referral
time = [7 , 17] # --> This is just for referral
weekdays = [1 ,2, 3, 4 ,5]

def gethours(sdate , edate):
    #Setting the start date    
    if sdate.isoweekday() == 6:
        sdate += datetime.timedelta(days=2)
        sdate = sdate.replace(hour = 7 , minute=0)
    elif sdate.isoweekday() == 7:
        sdate += datetime.timedelta(days=1)
        sdate = sdate.replace(hour = 7 , minute=0)
    elif ((sdate.isoweekday() in weekdays) & (sdate.hour > 17)):
        sdate += datetime.timedelta(days=1)
        if sdate.isoweekday() == 6:
            sdate += datetime.timedelta(days=2)
            sdate = sdate.replace(hour = 7 , minute=0)
        else:
            sdate = sdate.replace(hour = 7 , minute=0)
    elif ((sdate.isoweekday() in weekdays) & (sdate.hour == 17) & (sdate.minute > 0)):
        sdate += datetime.timedelta(days=1)
        if sdate.isoweekday() == 6:
            sdate += datetime.timedelta(days=2)
            sdate = sdate.replace(hour = 7 , minute=0)
        else:
            sdate = sdate.replace(hour = 7 , minute=0)
    elif ((sdate.isoweekday() in weekdays) & (sdate.hour < 7)):
        sdate = sdate.replace(hour = 7 , minute=0)
    else:
        sdate
    #Setting the end date
    if edate.isoweekday() == 6:
        edate += datetime.timedelta(days=2)
        edate = edate.replace(hour = 7 , minute=0)
    elif edate.isoweekday() == 7:
        edate += datetime.timedelta(days=1)
        edate = edate.replace(hour = 7 , minute=0)
    elif ((edate.isoweekday() in weekdays) & (edate.hour > 17)):
        edate += datetime.timedelta(days=1)
        if edate.isoweekday() == 6:
            edate += datetime.timedelta(days=2)
            edate = edate.replace(hour = 7 , minute=0)
        else:
            edate = edate.replace(hour = 7 , minute=0)
    elif ((edate.isoweekday() in weekdays) & (edate.hour == 17) & (edate.minute > 0) ):
        edate += datetime.timedelta(days=1)
        if edate.isoweekday() == 6:
            edate += datetime.timedelta(days=2)
            edate = edate.replace(hour = 7 , minute=0)
        else:
            edate = edate.replace(hour = 7 , minute=0)
    elif ((edate.isoweekday() in weekdays) & (edate.hour < 7)):
        edate = edate.replace(hour = 7 , minute=0)

    else:
        edate
    #Appproximating the bus days
    try:    
        days = np.busday_count(sdate , edate)
    #Calculating the hours    
        if days == 0:
            sec = (edate - sdate)
            sec = sec.total_seconds()
            hrs = sec // 3600
        elif days > 0:
            days = days - 1
            hrs1 = days * 10
            tdate1 = sdate.replace(hour = 17 , minute=0) 
            sec1 = (tdate1 - sdate)
            sec1 = sec1.total_seconds()
            hrss = sec1 // 3600
            tdate2 = edate.replace(hour = 7 , minute=0) 
            sec2 = edate - tdate2
            sec2 = sec2.total_seconds()
            hrse = sec2 // 3600
            hrs = hrs1 + hrss + hrse
    except ValueError:
        hrs = None
    if hrs is None:
        hrs = 0                           
    return hrs