基于Dataframe计算日期区间周数及各周天数的实现需求
拆分日期区间生成周相关字段的DataFrame处理方案
需求说明
我们需要处理一个包含ID、RID、PID、check_in、check_out字段的DataFrame,为每条记录计算日期区间内的周相关信息,新增以下4个字段:
Weekite:区间覆盖的周数Weekstart:区间起始日期所在周的周一(周起始日,样例中以周一为一周开端)Weekgrp:与Weekstart一致,用作周分组标识Days:区间内的实际天数(按小时差计算的完整天数)
输入输出样例
输入DataFrame
| ID | RID | PID | check_in | check_out |
|---|---|---|---|---|
| 10240 | 1 | 1 | 13-08-2014 9.30 | 14-08-2014 9.30 |
| 10240 | 2 | 1 | 16-08-2014 9.30 | 17-08-2014 9.30 |
| 10240 | 3 | 2 | 18-09-2012 9.30 | 25-09-2012 9.30 |
| 10240 | 4 | 1 | 25-09-2012 9.30 | 30-09-2012 9.30 |
| 10240 | 5 | 1 | 27-01-2015 22.30 | 27-02-2015 20.30 |
期望输出DataFrame
| ID | RID | PID | check_in | check_out | Weekite | Weekstart | Weekgrp | Days |
|---|---|---|---|---|---|---|---|---|
| 10240 | 1 | 1 | 13-08-2014 9.30 | 14-08-2014 9.30 | 1 | 10-08-2014 | 10-08-2014 | 1 |
| 10240 | 2 | 1 | 16-08-2014 9.30 | 17-08-2014 9.30 | 1 | 10-08-2014 | 10-08-2014 | 1 |
| 10240 | 3 | 2 | 18-09-2012 9.30 | 25-09-2012 9.30 | 1 | 17-09-2012 | 17-09-2012 | 7 |
| 10240 | 4 | 1 | 25-09-2012 9.30 | 30-09-2012 9.30 | 2 | 24-09-2012 | 24-09-2012 | 5 |
| 10240 | 5 | 1 | 27-01-2015 22.30 | 27-02-2015 20.30 | 5 | 26-01-2015 | 26-01-2015 | 30 |
解决方案(Python + Pandas)
下面是完整的代码实现,每一步都做了详细注释,方便理解:
import pandas as pd # 1. 构造输入DataFrame(如果是从文件读取,替换成pd.read_csv等方法即可) data = { "ID": [10240, 10240, 10240, 10240, 10240], "RID": [1, 2, 3, 4, 5], "PID": [1, 1, 2, 1, 1], "check_in": ["13-08-2014 9.30", "16-08-2014 9.30", "18-09-2012 9.30", "25-09-2012 9.30", "27-01-2015 22.30"], "check_out": ["14-08-2014 9.30", "17-08-2014 9.30", "25-09-2012 9.30", "30-09-2012 9.30", "27-02-2015 20.30"] } df = pd.DataFrame(data) # 2. 转换日期格式:把原格式的.替换成:,再解析为datetime类型 df["check_in"] = pd.to_datetime(df["check_in"].str.replace(".", ":"), format="%d-%m-%Y %H:%M") df["check_out"] = pd.to_datetime(df["check_out"].str.replace(".", ":"), format="%d-%m-%Y %H:%M") # 3. 计算Days字段:通过时间差的总秒数转换为天数,取整数部分 df["Days"] = (df["check_out"] - df["check_in"]).dt.total_seconds() / (24 * 3600) df["Days"] = df["Days"].astype(int) # 4. 计算Weekstart和Weekgrp:取check_in所在周的周一作为周起始日 # 注:pandas中dt.weekday的0代表周一,6代表周日;如果需要以周日为起始,可调整offset df["Weekstart"] = df["check_in"] - pd.to_timedelta(df["check_in"].dt.weekday, unit="D") # 格式化为dd-mm-yyyy的字符串格式 df["Weekstart"] = df["Weekstart"].dt.strftime("%d-%m-%Y") df["Weekgrp"] = df["Weekstart"] # 与Weekstart保持一致 # 5. 计算Weekite:计算区间覆盖的总周数 # 方法:先取check_out所在周的周一,再和check_in的周起始日计算间隔周数,最后加1 check_out_weekstart = df["check_out"] - pd.to_timedelta(df["check_out"].dt.weekday, unit="D") df["Weekite"] = ((check_out_weekstart - pd.to_datetime(df["Weekstart"])).dt.days // 7) + 1 # 6. 调整列顺序,与期望输出对齐 output_cols = ["ID", "RID", "PID", "check_in", "check_out", "Weekite", "Weekstart", "Weekgrp", "Days"] df = df[output_cols] # 可选:把日期列转回原字符串格式(如果不需要datetime类型的话) df["check_in"] = df["check_in"].dt.strftime("%d-%m-%Y %H.%M") df["check_out"] = df["check_out"].dt.strftime("%d-%m-%Y %H.%M") # 打印结果 print(df)
关键步骤解释
- 日期格式转换:原数据里的小时分钟用
.分隔,先替换成标准的:才能被pandas正确解析为时间类型。 - Days计算:通过时间差的总秒数除以一天的秒数,得到精确的天数,再转成整数确保是完整天数。
- Weekstart/Weekgrp:用当前日期减去对应的星期几的天数,快速定位到该周的周一;如果需要以周日为周起始,只需要调整offset即可(比如
df["check_in"] - pd.to_timedelta(df["check_in"].dt.dayofweek + 1, unit="D"))。 - Weekite计算:通过两个周起始日的间隔天数除以7,得到周数差,再加1就是区间覆盖的总周数,能准确跨周的情况。
内容的提问来源于stack exchange,提问作者Snehal Kakade
相关产品推荐
相关产品推荐

