代碼如下,復(fù)制后保存為擴展名為py的文件即可。
- 如未安裝pandas包,請使用pip install pandas進(jìn)行安裝。
- 代碼請結(jié)合附件,在python環(huán)境下使用。
- 確保附件保存在C盤根目錄下,否則請將代碼中的路徑改為正確的路徑。
由于代碼注釋已經(jīng)很詳細(xì)了,所以我這里就不再解釋了。
處理流程如下:
- 先處理系統(tǒng)錯誤(空值/數(shù)據(jù)類型等問題)。
- 然后處理邏輯錯誤(漏打卡,多打卡等問題)。
- 根據(jù)邏輯計算。
- 輸出結(jié)果。
----------------------------
import pandas as pd
df = pd.read_excel(r'C:\考勤記錄模板.xlsx')
# 預(yù)覽數(shù)據(jù)
print(df.head(10))
# 查看空值
print(df.isnull().sum())
# 刪除空值
df.dropna(subset='時間', inplace=True)
print(df.isnull().sum())
# 修改日期格式
df['日期'] = df['日期'].apply(
lambda x: pd.to_datetime('1900-1-1')
+ pd.DateOffset(x))
df['時間'] = pd.to_datetime(
df['時間'], format='%H:%M:%S')
print(df.head(20))
# 添加打卡次數(shù),以便檢查多打卡或漏打卡的情況。
df['打卡次數(shù)'] = df.groupby(['工號', '日期'])['時間'].rank()
print(df.head(20))
df_times = df.groupby(['工號', '日期'])['打卡次數(shù)'].agg(
['min', 'max'])
df_times = df_times.reset_index()
print(df_times.head())
df_new = pd.merge(df, df_times, on=['工號', '日期'])
print(df_new.head())
# 多打卡的位置介乎最小值和最大值之間,因此將兩者與打卡次數(shù)相減,必然大于0
df_new['多打卡'] = (df_new['打卡次數(shù)'] - df_new['min']) * (df_new['max'] - df_new['打卡次數(shù)'])
df_new = df_new[df_new['多打卡'] == 0]
print(df_new.head(10))
# 漏打卡的最大值和最小值相同,相減得0
df_new['打卡次數(shù)差'] = df_new['max'] - df_new['min']
df_new['漏打卡'] = df_new['打卡次數(shù)差'].apply(lambda x: '是' if x == 0 else '否')
print(df_new.head(10))
# 漏打卡沒法算遲到,補卡后再處理
'''
基于以上表格,給我算出每個人,每天的遲到,早退,加班時長。
具體邏輯如下:
遲到:時間大于8:35:01算遲到
早退:時間小于16:29:59算早退;周六11:30:00之前算早退.
加班時長:工作日:16:30:00后算加班,未達(dá)到17:30:00不算加班,17:30:00后滿半小時都算加班;
周六:12:30:00以后算加班,周日:8:35:01后算加班
'''
df_new['星期'] = df_new['日期'].dt.strftime('%a')
print(df_new.head(10))
# 判斷遲到/早退/加班。
def get_work_type(df_time, df_weekday, is_mark=True):
start_time = pd.to_datetime('1900-01-01 8:35:01')
work_type = None
work_time = pd.Timedelta(0)
if df_weekday == 'Sat':
end_time = pd.to_datetime('1900-01-01 11:30:00')
ot_start_time = pd.to_datetime('1900-01-01 12:30:00')
elif df_weekday == 'Sun':
end_time = pd.to_datetime('1900-01-01 8:35:01')
ot_start_time = pd.to_datetime('1900-01-01 8:35:01')
else:
end_time = pd.to_datetime('1900-01-01 16:30:00')
ot_start_time = pd.to_datetime('1900-01-01 18:00:00')
# 打卡時間介乎下班和上班之間
if start_time < df_time < end_time:
# 打卡時間接近上班則算遲早,否則算早退
if df_time - start_time <= end_time - df_time:
work_type = '遲到'
work_time = df_time - start_time
else:
work_type = '早退'
work_time = end_time - df_time
# 如果下班時間大于加班起始時間
elif df_time > ot_start_time:
work_type = '加班'
work_time = df_time - ot_start_time
# 根據(jù)傳入值選擇輸出時間或者標(biāo)簽。
if is_mark:
return work_type
else:
return work_time
# 生成類型和時長
df_new['類型'] = df_new.apply(
lambda x: get_work_type(x['時間'], x['星期']), axis=1)
df_new[df_new['類型'].notnull()]
df_new['時長'] = df_new.apply(
lambda x: get_work_type(x['時間'], x['星期'], False), axis=1)
df_new[df_new['類型'].notnull()]
columns = ['工號', '姓名', '部門', '日期', '時間', '漏打卡', '類型', '時長']
print(df_new.columns)
df_result = df_new[columns]
df_result.to_excel(r'C:\考勤記錄.xlsx', '處理結(jié)果', index=False)
----------------------------