You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何为Pandas DataFrame添加列判断日期范围是否覆盖任意年份7月

问题:判断Pandas DataFrame日期范围是否覆盖任意年份7月

现有带start(起始日期)和finish(结束日期)列的Pandas DataFrame,需新增existed_in_july列,判断每条记录的日期范围是否覆盖过任意年份的完整7月。

初始DataFrame示例代码:

import pandas as pd
import datetime as dt

df = pd.DataFrame(
    {
         "start": [dt.datetime(2020,1,1), dt.datetime(2020,8,1), dt.datetime(2020,8,1)],
         "finish": [dt.datetime(2021,12,1), dt.datetime(2021,6,1), dt.datetime(2022,6,1)],
     })

仅针对2020年7月的判断代码如下,但无法覆盖其他年份的7月(比如第三条记录覆盖2021年7月):

df['existed_in_july_2020'] = (df['start'] < dt.datetime(2020,7,1)) & (df['finish'] >= dt.datetime(2020,8,1))

预期结果:

df = pd.DataFrame(
    {
         "start": [dt.datetime(2020,1,1), dt.datetime(2020,8,1), dt.datetime(2020,8,1)],
         "finish": [dt.datetime(2021,12,1), dt.datetime(2021,6,1), dt.datetime(2022,6,1)],
         "existed_in_july": [True, False, True]
     })

解决方案

方法1:逐行遍历年份检查(易理解,适合小数据集)

通过遍历每条记录涉及的所有年份,检查对应年份的7月是否被日期范围完整覆盖:

def covers_any_july(row):
    start_year = row['start'].year
    end_year = row['finish'].year
    for year in range(start_year, end_year + 1):
        july_start = dt.datetime(year, 7, 1)
        july_end = dt.datetime(year, 8, 1)
        if row['start'] < july_start and row['finish'] >= july_end:
            return True
    return False

df['existed_in_july'] = df.apply(covers_any_july, axis=1)

方法2:矢量化操作(高效,适合大数据集)

利用Pandas的日期属性做矢量化判断,避免循环,提升效率,核心逻辑分三种情况:

  1. 日期范围跨≥2个完整年份:必然覆盖中间年份的7月
  2. 日期范围在同一年份:判断该年份7月是否被包含
  3. 日期范围跨2个年份:检查起始年或结束年的7月是否被覆盖

代码实现:

# 提取日期属性
df['start_year'] = df['start'].dt.year
df['start_month'] = df['start'].dt.month
df['finish_year'] = df['finish'].dt.year
df['finish_month'] = df['finish'].dt.month

# 定义三种覆盖情况
case1 = (df['finish_year'] - df['start_year']) >= 2
case2 = (df['start_year'] == df['finish_year']) & (df['start_month'] < 7) & (df['finish_month'] >= 7)
case3 = (df['finish_year'] - df['start_year'] == 1) & (
    (df['start_month'] < 7) | (df['finish_month'] >= 7)
)

# 合并结果
df['existed_in_july'] = case1 | case2 | case3

# 清理临时列
df.drop(['start_year', 'start_month', 'finish_year', 'finish_month'], axis=1, inplace=True)

两种方法都能得到预期的existed_in_july列,方法2的矢量化操作在处理大规模数据时优势明显。


内容的提问来源于stack exchange,提问作者Chris Dixon

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.27 02:45:35