使用Pandas计算月度工作日天数:现有方法含周末需调整
计算月度工作日天数(排除周末)
嘿,这个问题我熟!要计算每个月的工作日天数(排除周六周日),你已经有了每个月的起始日期和下个月的起始日期,刚好可以用pandas的bdate_range来搞定——这玩意儿专门用来生成工作日日期范围,完美匹配你的需求。
核心思路
pd.bdate_range()会自动生成两个日期之间的所有工作日(默认跳过周六周日),我们只需要用这个函数生成当月的工作日范围,再统计它的长度就是当月的工作日天数了。因为你的Signin Date Shifted是下个月的第一天,所以需要把它减一天,得到当月的最后一天,作为日期范围的结束点。
具体实现代码
假设你的df2已经有了Signin Date和Signin Date Shifted两列,直接用apply函数就能快速计算:
import pandas as pd # 计算每个月的工作日天数 df2['Workdays'] = df2.apply( lambda row: len(pd.bdate_range( start=row['Signin Date'], end=row['Signin Date Shifted'] - pd.Timedelta(days=1) )), axis=1 )
示例验证
比如我们用几个测试月份来跑一下:
# 构造示例数据 data = {'Signin Date': pd.to_datetime(['2023-01-01', '2023-02-01', '2023-03-01'])} df2 = pd.DataFrame(data) df2['Signin Date Shifted'] = df2['Signin Date'] + pd.DateOffset(months=1) # 计算工作日 df2['Workdays'] = df2.apply( lambda x: len(pd.bdate_range(start=x['Signin Date'], end=x['Signin Date Shifted'] - pd.Timedelta(days=1))), axis=1 ) print(df2)
输出结果会是:
Signin Date Signin Date Shifted Workdays 0 2023-01-01 2023-02-01 22 1 2023-02-01 2023-03-01 20 2 2023-03-01 2023-04-01 23
进阶:排除法定节假日
如果还需要排除法定节假日,只需要给bdate_range加上holidays参数就行。比如定义你的节假日列表,然后传入:
# 示例节假日(根据你的实际需求调整) holidays = pd.to_datetime(['2023-01-02', '2023-01-16']) df2['Workdays'] = df2.apply( lambda row: len(pd.bdate_range( start=row['Signin Date'], end=row['Signin Date Shifted'] - pd.Timedelta(days=1), holidays=holidays )), axis=1 )
这样计算出来的天数就会同时排除周末和指定的节假日啦。
内容的提问来源于stack exchange,提问作者scarecrow




