如何无需循环为DataFrame添加日期区间判断列?
问题:为DataFrame新增日期区间判断列(无循环实现)
我有一个包含date列的DataFrame,同时拥有两个日期列表:一个是开始日期列表,另一个是结束日期列表(二者长度相同)。我想要新增一列名为variable的列,当date处于任意一对起止日期区间内时,该列值为1,否则为0。我尝试了以下代码,但无法正常运行。请问有没有无需循环的实现方法?
start_dates = [date(2023,4,1), date(2023,4,24), date(2023,5,15)] end_dates = [date(2023,4,14), date(2023,5,1), date(2023,5,30)] no_days = 92 intervals = [date(2023, 3, 1) + timedelta(days=1*i) for i in range(0, no_days-2)] df = pd.DataFrame({'date':intervals}) # 无法正常运行的代码 df.assign(variable=np.where((df.date >= start) & (df.date <= end), 1, 0) for start in start_dates for end in end_dates)
无循环实现方案
方法1:利用NumPy广播机制
通过将日期列转换为二维数组,与起止日期数组进行广播比较,再判断每个日期是否满足任意区间条件:
import pandas as pd from datetime import date, timedelta import numpy as np start_dates = [date(2023,4,1), date(2023,4,24), date(2023,5,15)] end_dates = [date(2023,4,14), date(2023,5,1), date(2023,5,30)] no_days = 92 intervals = [date(2023, 3, 1) + timedelta(days=1*i) for i in range(0, no_days-2)] df = pd.DataFrame({'date':intervals}) # 转换数组实现广播 dates_np = df['date'].to_numpy()[:, np.newaxis] starts_np = np.array(start_dates) ends_np = np.array(end_dates) # 生成掩码并转换为1/0 mask = ((dates_np >= starts_np) & (dates_np <= ends_np)).any(axis=1) df['variable'] = mask.astype(int)
方法2:使用Pandas IntervalIndex
将起止日期对转换为IntervalIndex,直接用isin方法判断日期是否落在任意区间内:
import pandas as pd from datetime import date, timedelta start_dates = [date(2023,4,1), date(2023,4,24), date(2023,5,15)] end_dates = [date(2023,4,14), date(2023,5,1), date(2023,5,30)] no_days = 92 intervals = [date(2023, 3, 1) + timedelta(days=1*i) for i in range(0, no_days-2)] df = pd.DataFrame({'date':intervals}) # 创建区间索引并判断 interval_index = pd.IntervalIndex.from_arrays(start_dates, end_dates, closed='both') df['variable'] = df['date'].isin(interval_index).astype(int)
两种方法均无需显式循环,处理大数据量时效率远高于循环实现。
内容的提问来源于stack exchange,提问作者corianne1234
相关产品推荐
相关产品推荐

