我有五年的金融相关数据。财政年度从7月1日开始,到6月30日结束。我想计算每个财政年度的财政周。我想对数据框的日期列应用一些操作,这样当我写类似df['date].dt.week
的东西时,它应该返回财务周数,而不是返回日历周数。因此,我使用以下代码来执行所需的输出:
df['date'] = df['date'].apply(pd.Period,freq='W')
df['date'].dt.week
但它并没有产生预期的结果。有人能告诉我哪里出了错吗?
我认为pandas
无法做到这一点。但是,您可以使用我在下面创建的名为business_week
的矢量化函数(当我使用它时,我也为business day
创建了一个(。这些函数说明闰年。此功能从您经过的月份/日期的第一天开始计数,而不是从一周中的特定日期开始计数。请注意,一年中有52个完整的星期,根据闰年的不同,还有1或2个额外的日子,因此6月30日将显示为53
周,6月29日也将显示为闰年。如果你想让53变成52,你可以简单地用52代替53。您必须传递以下参数:
- 要以日期时间格式导出工作周的列
- 开始月份
- 开始日期
例如:df['week'] = business_week(df['date'], 7, 1)
和下面的最小可复制示例:
df = pd.DataFrame({'date':
{0: pd.Timestamp('2019-01-01 00:00:00'),
1: pd.Timestamp('2019-06-28 00:00:00'),
2: pd.Timestamp('2019-06-29 00:00:00'),
3: pd.Timestamp('2019-06-30 00:00:00'),
4: pd.Timestamp('2019-07-01 00:00:00'),
5: pd.Timestamp('2019-07-07 00:00:00'),
6: pd.Timestamp('2019-07-08 00:00:00'),
7: pd.Timestamp('2020-01-01 00:00:00'),
8: pd.Timestamp('2020-06-28 00:00:00'),
9: pd.Timestamp('2020-06-29 00:00:00'),
10: pd.Timestamp('2020-06-30 00:00:00'),
11: pd.Timestamp('2020-07-01 00:00:00'),
12: pd.Timestamp('2020-07-07 00:00:00'),
13: pd.Timestamp('2020-07-08 00:00:00')}})
def business_week(d, start_month, start_day):
from datetime import datetime, timedelta
y_int = d.dt.year
y_str = y_int.astype(str)
start_md = (datetime(2020, start_month, start_day) - timedelta(days=1)).strftime('%m-%d')
start_ymd = pd.to_datetime(y_str + '-' + start_md)
s = d.dt.dayofyear - start_ymd.dt.dayofyear
m1 = s.mask(s < 1, 365 - abs(s))
m2 = m1.mask((y_int % 4 == 0) & (d > start_ymd), m1 - 1)
return np.where(y_int % 4 != 0, (m2 + 6) / 7, (m2 + 7) / 7).astype(int)
df['week'] = business_week(df['date'], 7, 1)
df
Out[1]:
date week
0 2019-01-01 27
1 2019-06-28 52
2 2019-06-29 52
3 2019-06-30 53
4 2019-07-01 1
5 2019-07-07 1
6 2019-07-08 2
7 2020-01-01 27
8 2020-06-28 52
9 2020-06-29 53
10 2020-06-30 53
11 2020-07-01 1
12 2020-07-07 1
13 2020-07-08 2
此外,如果您需要,可以使用类似的方法返回business_day
:
def business_day(d, start_month, start_day):
from datetime import datetime, timedelta
y_int = d.dt.year
y_str = y_int.astype(str)
start_md = (datetime(2020, start_month, start_day) - timedelta(days=1)).strftime('%m-%d')
start_ymd = pd.to_datetime(y_str + '-' + start_md)
s = d.dt.dayofyear - start_ymd.dt.dayofyear
m1 = s.mask(s < 1, 365 - abs(s))
m2 = m1.mask((y_int % 4 == 0) & (d <= start_ymd), m1 + 1)
return m2
df['day'] = business_day(df['date'], 7, 1)
df
Out[1]:
date day
0 2019-01-01 185
1 2019-06-28 363
2 2019-06-29 364
3 2019-06-30 365
4 2019-07-01 1
5 2019-07-07 7
6 2019-07-08 8
7 2020-01-01 185
8 2020-06-28 364
9 2020-06-29 365
10 2020-06-30 366
11 2020-07-01 1
12 2020-07-07 7
13 2020-07-08 8
Series.dt.week
id已弃用。我还没有遇到一个财政年度周。也许可以将周初编号设置为从某个日期开始。
正常的一年中的一周数字我会在强制日期到日期的时间后尝试以下内容
df.date.apply(lambda x: pd.Period(x,freq='D').week)
或
df['date'].dt.strftime("%W").astype(int)