如何为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的日期属性做矢量化判断,避免循环,提升效率,核心逻辑分三种情况:
- 日期范围跨≥2个完整年份:必然覆盖中间年份的7月
- 日期范围在同一年份:判断该年份7月是否被包含
- 日期范围跨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
相关产品推荐
相关产品推荐

