Python 创建具有任意开始日期的月度时间序列
使用Python 创建具有任意开始日期的月度时间序列,python,pandas,python-datetime,Python,Pandas,Python Datetime,使用pandas可以轻松创建每月的日期序列 import pandas as pd pd.date_range('2012-04-23', '2013-01-23', freq='BM') DatetimeIndex(['2012-04-30', '2012-05-31', '2012-06-29', '2012-07-31', '2012-08-31', '2012-09-28', '2012-10-31', '2012-11-30',
pandas
可以轻松创建每月的日期序列
import pandas as pd
pd.date_range('2012-04-23', '2013-01-23', freq='BM')
DatetimeIndex(['2012-04-30', '2012-05-31', '2012-06-29', '2012-07-31',
'2012-08-31', '2012-09-28', '2012-10-31', '2012-11-30',
'2012-12-31'],
dtype='datetime64[ns]', freq='BM')
请注意,DatetimeIndex
中的日期是月末。我知道应该考虑我选择了freq='BM'
,但我不相信我有一个能够实现我目标的选择
我经常需要从每个月的最后一个工作日开始制作一系列的日期
我想看看这个:
DatetimeIndex(['2012-04-23', '2012-05-23', '2012-06-23', '2012-07-23',
'2012-08-23', '2012-09-23', '2012-10-23', '2012-11-23',
'2012-12-23'],
dtype='datetime64[ns]', freq=None)
或者另一个更复杂的例子可能是从“2012-01-30”到“2012-04-30”有几个月的时间。我希望看到:
DatetimeIndex(['2012-01-30', '2012-02-29', '2012-03-30', '2012-04-30'],
dtype='datetime64[ns]', freq=None)
我不清楚你的问题,但我相信这是一个正确的方向
start = '2012-04-23'
end = '2013-01-23'
>>> pd.DatetimeIndex([pd.datetime(ts.year, ts.month, int(end.split("-")[-1]))
for ts in pd.date_range(start, end, freq='BM')])
DatetimeIndex(['2012-04-23', '2012-05-23', '2012-06-23', '2012-07-23', '2012-08-23', '2012-09-23', '2012-10-23', '2012-11-23', '2012-12-23'], dtype='datetime64[ns]', freq=None)
虽然没有针对速度进行优化,但我相信以下函数将根据您的要求返回正确的值
def foo(date, periods, forward=True):
if isinstance(date, str):
date = pd.Timestamp(date).date()
dates = [date + relativedelta(date, months=n * (1 if forward else -1)) for n in range(1, periods +1)]
result = []
print dates
for date in dates:
month = date.month
iso_day = date.isoweekday()
if iso_day == 6:
date += dt.timedelta(days=2 if forward else -1)
elif iso_day == 7:
date += dt.timedelta(days=1 if forward else -2)
if date.month != month:
# Gone into next/preceding month. Roll back/forward.
date -= dt.timedelta(days=3 if forward else -3)
result.append(date)
return result
您可能正在寻找以下内容:
from pandas.tseries.offsets import Day, BDay
pd.date_range(start = '2012-01-01', periods = 6, freq = 'MS') + Day(22) + BDay(0)
Out[12]:
DatetimeIndex(['2012-01-23', '2012-02-23', '2012-03-23', '2012-04-23',
'2012-05-23', '2012-06-25'],
dtype='datetime64[ns]', freq=None)
Day(22)
添加22天的偏移量,BDay
负责工作日偏移量(BDay(0)
取最近的工作日)
从30号开始约会有点困难。所以我必须为此写一个函数。(为了代码清晰,它不允许自定义freq
参数。)
def my_business_date_范围(天,**kwargs):
断言(isinstance(天,整数)和(天>0)和(天<32))
rng0=pd.日期\范围(频率='MS',**kwargs)
rng1=rng0+pd.tseries.offset.Day(第1天)+pd.tseries.offset.BDay(0)
#纠正溢出:
溢出\u idx,=np.非零(rng0.month!=rng1.month)
如果溢出_idx.size>0:
#rng1是不可变的
tmp=rng1.tolist()
bme=pd.tseries.offset.BusinessMonthEnd(-1)
对于溢出_idx中的i:
tmp[i]=bme(rng1[i])
rng1=pd.DatetimeIndex(tmp)
返回rng1
我的业务日期范围(30,开始日期='2012-01-01',期间=6)
出[13]:
DatetimeIndex(['2012-01-30','2012-02-29','2012-03-30','2012-04-30',',
'2012-05-30', '2012-06-29'],
dtype='datetime64[ns]',freq=None)
熊猫队也有一个实验项目,但我无法让它工作。我不明白。您刚才问的似乎不是您希望看到的,即,top DatetimeIndex是该月的最后一个工作日,可以追溯到时间。@Alexander这是因为我不知道将什么作为
freq
参数。我不想每天生产,我相信这是默认的。所以今天是5月6日(已经?!?…)。3月6日是星期天。你想看什么?三月四日(星期五)?@亚历山大:是的。但我在问题中没有具体说明这一点。我不想把它复杂化。这对于我在本例中使用的特定日期集肯定有效。我已经有了一个健壮的,如果是复杂的解决方案。我想征求其他意见,这样我可能会有一个更清晰的答案。在我的问题中,我将继续补充一些评论。“BM”似乎不是有效的选项。如果今天是2016年6月1日(星期三)。2016-05-01是星期天,你想看2016-04-28(星期五)吗?这是一个很好的问题。我必须选择2016-05-02。我的解决方案包括一次回滚一个月,并考虑多个因素做出决策,例如,是否是周末,如果是,则回滚,除非该值下降到上个月(您的示例),否则回滚。原始日期是月末、营业月末还是开始日期,应该保留结束日期还是开始日期。您是选择结束日期并按照这些规则向后工作,还是选择开始日期并向前工作?这很好。对有趣的函数有很多很好的见解和参考。谢谢你的努力。
def my_business_date_range(day, **kwargs):
assert(isinstance(day, int) & (day > 0) & (day < 32))
rng0 = pd.date_range(freq = 'MS', **kwargs)
rng1 = rng0 + pd.tseries.offsets.Day(day-1) + pd.tseries.offsets.BDay(0)
# Correcting overflows:
overflow_idx, = np.nonzero(rng0.month != rng1.month)
if overflow_idx.size > 0:
# rng1 is not mutable
tmp = rng1.tolist()
bme = pd.tseries.offsets.BusinessMonthEnd(-1)
for i in overflow_idx:
tmp[i] = bme(rng1[i])
rng1 = pd.DatetimeIndex(tmp)
return rng1
my_business_date_range(30, start= '2012-01-01', periods = 6)
Out[13]:
DatetimeIndex(['2012-01-30', '2012-02-29', '2012-03-30', '2012-04-30',
'2012-05-30', '2012-06-29'],
dtype='datetime64[ns]', freq=None)