我有两列,“start_date”和“end_date”,它们可以是各种日期,从一天(日期之间没有差异)到相隔 18 个月。然而,我正在使用的 API 只需要 7 天的日期间隔,因此我想将用户提供的日期范围解析为每 7 天的唯一行(并且不超过提供的结束日期)。
我用 udf 成功实现了这一点,但我很好奇是否有一种我没有想到的更有效的方法。这是我开始使用的数据框:
foo start_date end_date
foo1 2017-08-01 2017-09-01
我把它改成了这样:
foo start_date end_date
foo1 2017-08-01 2017-08-07
foo1 2017-08-08 2017-08-14
foo1 2017-08-15 2017-08-21
foo1 2017-08-22 2017-08-28
foo1 2017-08-29 2017-09-01
这是我的代码。它可以工作,并且对于我的数据目的来说很好,因为我一次只能分割大约 40 行......但该解决方案感觉异常笨拙。我很好奇是否有更有效的方法。
def list_of_weeks(start,end):
if start == end:
return start
else:
start, end = datetime.strptime(start, '%Y-%m-%d'), datetime.strptime(end, '%Y-%m-%d')
dates = [start]
curr_date = start
end = end - timedelta(7)
while curr_date <= end:
curr_date += timedelta(7)
dates.append(curr_date)
dates = ','.join([x.strftime('%Y-%m-%d') for x in dates])
return dates
end = df.select('end_date').collect()[0][0]
end = datetime.strptime(end, '%Y-%m-%d')
list_of_weeks_udf = udf(list_of_weeks)
df = (df.withColumn('start_date', split(list_of_weeks_udf('start_date','end_date'), ','))
.withColumn('start_date', explode('start_date'))
.withColumn('start_date', to_date('start_date'))
.withColumn('end_date', date_add('start_date', 6))
.withColumn('end_date', when(col('end_date')>end, end.strftime('%Y-%m-%d')).otherwise(col('end_date'))))
最佳答案
这是使用pandas' date_range :
import pandas
start, end = '2017-08-01', '2017-09-01'
d1 = pandas.date_range(start=start, end=end, freq='7D')
d2 = d1.shift(6, freq='d')
# fix end date (make sure latest end_date it doesn't go over end_date)
d2 = list(d2)[:-1] + [min(d2[-1], pandas.Timestamp(end))]
df = pandas.DataFrame(data=dict(foo=['foo1']*len(d1), start_date=d1, end_date=d2),
columns=('foo', 'start_date', 'end_date'))
print(df.to_string(index=False))
打印:
foo start_date end_date
foo1 2017-08-01 2017-08-07
foo1 2017-08-08 2017-08-14
foo1 2017-08-15 2017-08-21
foo1 2017-08-22 2017-08-28
foo1 2017-08-29 2017-09-01
顺便说一句,由于 index=False
,理由似乎略有偏差,请参阅 this open pandas bug
关于python - 给定开始日期和结束日期,生成中间所有周的最有效方法是什么?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/48131816/