我在数据框中有一个列,它告诉我日期是否是假期。这是一个示例:
dates is_holiday
2019-02-14 NaN
2019-02-15 NaN
2019-02-16 NaN
2019-02-17 NaN
2019-02-18 Family Day
2019-02-19 NaN
2019-02-20 NaN
2019-02-21 NaN
2019-02-22 NaN
2019-02-23 NaN
2019-02-24 NaN
我想创建一个列,该列可统计到下一个假期为止有多少天,以及从上一个假期以来有多少天,最多5天。上面示例的所需输出
dates days_to_holiday
2019-02-14 4
2019-02-15 3
2019-02-16 2
2019-02-17 1
2019-02-18 0
2019-02-19 -1
2019-02-20 -2
2019-02-21 -3
2019-02-22 -4
2019-02-23 -5
2019-02-24 NaN
距离家庭日(2019-02-18)2019-02-14有4天,而距离家庭日2019-02-20有2天。由于我不希望假期前后数超过5天,因此2018-02-24仍然是NaN。
为澄清起见,列is_holiday
中有几个假期。这是一个更大的例子。
dates is_holiday
2018-01-01 New Year's Day
2018-01-02 NaN
2018-01-03 NaN
2018-01-04 NaN
2018-01-05 NaN
2018-01-06 NaN
2018-01-07 NaN
2018-01-08 NaN
2018-01-09 NaN
2018-01-10 NaN
2018-01-11 NaN
2018-01-12 NaN
2018-01-13 NaN
2018-01-14 NaN
2018-01-15 NaN
2018-01-16 NaN
2018-01-17 NaN
2018-01-18 NaN
2018-01-19 NaN
2018-01-20 NaN
2018-01-21 NaN
2018-01-22 NaN
2018-01-23 NaN
2018-01-24 NaN
2018-01-25 NaN
2018-01-26 NaN
2018-01-27 NaN
2018-01-28 NaN
2018-01-29 NaN
2018-01-30 NaN
2018-01-31 NaN
2018-02-01 NaN
2018-02-02 NaN
2018-02-03 NaN
2018-02-04 NaN
2018-02-05 NaN
2018-02-06 NaN
2018-02-07 NaN
2018-02-08 NaN
2018-02-09 NaN
2018-02-10 NaN
2018-02-11 NaN
2018-02-12 NaN
2018-02-13 NaN
2018-02-14 NaN
2018-02-15 NaN
2018-02-16 NaN
2018-02-17 NaN
2018-02-18 NaN
2018-02-19 Family Day
2018-02-20 NaN
2018-02-21 NaN
2018-02-22 NaN
2018-02-23 NaN
2018-02-24 NaN
2018-02-25 NaN
2018-02-26 NaN
2018-02-27 NaN
2018-02-28 NaN
2018-03-01 NaN
2018-03-02 NaN
2018-03-03 NaN
2018-03-04 NaN
2018-03-05 NaN
2018-03-06 NaN
2018-03-07 NaN
2018-03-08 NaN
2018-03-09 NaN
2018-03-10 NaN
2018-03-11 NaN
2018-03-12 NaN
2018-03-13 NaN
2018-03-14 NaN
2018-03-15 NaN
2018-03-16 NaN
2018-03-17 NaN
2018-03-18 NaN
2018-03-19 NaN
2018-03-20 NaN
2018-03-21 NaN
2018-03-22 NaN
2018-03-23 NaN
2018-03-24 NaN
2018-03-25 NaN
2018-03-26 NaN
2018-03-27 NaN
2018-03-28 NaN
2018-03-29 NaN
2018-03-30 Good Friday
2018-03-31 NaN
2018-04-01 NaN
2018-04-02 NaN
2018-04-03 NaN
2018-04-04 NaN
2018-04-05 NaN
2018-04-06 NaN
2018-04-07 NaN
2018-04-08 NaN
2018-04-09 NaN
2018-04-10 NaN
2018-04-11 NaN
2018-04-12 NaN
2018-04-13 NaN
2018-04-14 NaN
2018-04-15 NaN
2018-04-16 NaN
2018-04-17 NaN
2018-04-18 NaN
2018-04-19 NaN
2018-04-20 NaN
2018-04-21 NaN
2018-04-22 NaN
2018-04-23 NaN
2018-04-24 NaN
2018-04-25 NaN
2018-04-26 NaN
2018-04-27 NaN
2018-04-28 NaN
2018-04-29 NaN
2018-04-30 NaN
2018-05-01 NaN
2018-05-02 NaN
2018-05-03 NaN
2018-05-04 NaN
2018-05-05 NaN
2018-05-06 NaN
2018-05-07 NaN
2018-05-08 NaN
2018-05-09 NaN
2018-05-10 NaN
2018-05-11 NaN
2018-05-12 NaN
2018-05-13 NaN
2018-05-14 NaN
2018-05-15 NaN
2018-05-16 NaN
2018-05-17 NaN
2018-05-18 NaN
2018-05-19 NaN
2018-05-20 NaN
2018-05-21 Victoria Day
2018-05-22 NaN
2018-05-23 NaN
2018-05-24 NaN
2018-05-25 NaN
2018-05-26 NaN
2018-05-27 NaN
2018-05-28 NaN
2018-05-29 NaN
2018-05-30 NaN
2018-05-31 NaN
2018-06-01 NaN
2018-06-02 NaN
2018-06-03 NaN
2018-06-04 NaN
2018-06-05 NaN
2018-06-06 NaN
2018-06-07 NaN
2018-06-08 NaN
2018-06-09 NaN
2018-06-10 NaN
2018-06-11 NaN
2018-06-12 NaN
2018-06-13 NaN
2018-06-14 NaN
2018-06-15 NaN
2018-06-16 NaN
2018-06-17 NaN
2018-06-18 NaN
2018-06-19 NaN
2018-06-20 NaN
2018-06-21 NaN
2018-06-22 NaN
2018-06-23 NaN
2018-06-24 NaN
2018-06-25 NaN
2018-06-26 NaN
2018-06-27 NaN
2018-06-28 NaN
2018-06-29 NaN
2018-06-30 NaN
2018-07-01 Canada Day
2018-07-02 Canada Day (Observed)
2018-07-03 NaN
2018-07-04 NaN
2018-07-05 NaN
2018-07-06 NaN
2018-07-07 NaN
2018-07-08 NaN
2018-07-09 NaN
2018-07-10 NaN
2018-07-11 NaN
2018-07-12 NaN
2018-07-13 NaN
2018-07-14 NaN
2018-07-15 NaN
2018-07-16 NaN
2018-07-17 NaN
2018-07-18 NaN
2018-07-19 NaN
2018-07-20 NaN
2018-07-21 NaN
2018-07-22 NaN
2018-07-23 NaN
2018-07-24 NaN
2018-07-25 NaN
2018-07-26 NaN
2018-07-27 NaN
2018-07-28 NaN
2018-07-29 NaN
2018-07-30 NaN
2018-07-31 NaN
2018-08-01 NaN
2018-08-02 NaN
2018-08-03 NaN
2018-08-04 NaN
2018-08-05 NaN
2018-08-06 Civic Holiday
2018-08-07 NaN
2018-08-08 NaN
2018-08-09 NaN
2018-08-10 NaN
2018-08-11 NaN
2018-08-12 NaN
2018-08-13 NaN
2018-08-14 NaN
2018-08-15 NaN
2018-08-16 NaN
2018-08-17 NaN
2018-08-18 NaN
2018-08-19 NaN
2018-08-20 NaN
2018-08-21 NaN
2018-08-22 NaN
2018-08-23 NaN
2018-08-24 NaN
2018-08-25 NaN
2018-08-26 NaN
2018-08-27 NaN
2018-08-28 NaN
2018-08-29 NaN
2018-08-30 NaN
2018-08-31 NaN
2018-09-01 NaN
2018-09-02 NaN
2018-09-03 Labour Day
2018-09-04 NaN
2018-09-05 NaN
2018-09-06 NaN
2018-09-07 NaN
2018-09-08 NaN
2018-09-09 NaN
2018-09-10 NaN
2018-09-11 NaN
2018-09-12 NaN
2018-09-13 NaN
2018-09-14 NaN
2018-09-15 NaN
2018-09-16 NaN
2018-09-17 NaN
2018-09-18 NaN
2018-09-19 NaN
2018-09-20 NaN
2018-09-21 NaN
2018-09-22 NaN
2018-09-23 NaN
2018-09-24 NaN
2018-09-25 NaN
2018-09-26 NaN
2018-09-27 NaN
2018-09-28 NaN
2018-09-29 NaN
2018-09-30 NaN
2018-10-01 NaN
2018-10-02 NaN
2018-10-03 NaN
2018-10-04 NaN
2018-10-05 NaN
2018-10-06 NaN
2018-10-07 NaN
2018-10-08 Thanksgiving
2018-10-09 NaN
2018-10-10 NaN
2018-10-11 NaN
2018-10-12 NaN
2018-10-13 NaN
2018-10-14 NaN
2018-10-15 NaN
2018-10-16 NaN
2018-10-17 NaN
2018-10-18 NaN
2018-10-19 NaN
2018-10-20 NaN
2018-10-21 NaN
2018-10-22 NaN
2018-10-23 NaN
2018-10-24 NaN
2018-10-25 NaN
2018-10-26 NaN
2018-10-27 NaN
2018-10-28 NaN
2018-10-29 NaN
2018-10-30 NaN
2018-10-31 NaN
2018-11-01 NaN
2018-11-02 NaN
2018-11-03 NaN
2018-11-04 NaN
2018-11-05 NaN
2018-11-06 NaN
2018-11-07 NaN
2018-11-08 NaN
2018-11-09 NaN
2018-11-10 NaN
2018-11-11 NaN
2018-11-12 NaN
2018-11-13 NaN
2018-11-14 NaN
2018-11-15 NaN
2018-11-16 NaN
2018-11-17 NaN
2018-11-18 NaN
2018-11-19 NaN
2018-11-20 NaN
2018-11-21 NaN
2018-11-22 NaN
2018-11-23 NaN
2018-11-24 NaN
2018-11-25 NaN
2018-11-26 NaN
2018-11-27 NaN
2018-11-28 NaN
2018-11-29 NaN
2018-11-30 NaN
2018-12-01 NaN
2018-12-02 NaN
2018-12-03 NaN
2018-12-04 NaN
2018-12-05 NaN
2018-12-06 NaN
2018-12-07 NaN
2018-12-08 NaN
2018-12-09 NaN
2018-12-10 NaN
2018-12-11 NaN
2018-12-12 NaN
2018-12-13 NaN
2018-12-14 NaN
2018-12-15 NaN
2018-12-16 NaN
2018-12-17 NaN
2018-12-18 NaN
2018-12-19 NaN
2018-12-20 NaN
2018-12-21 NaN
2018-12-22 NaN
2018-12-23 NaN
2018-12-24 NaN
2018-12-25 Christmas Day
2018-12-26 Boxing Day
2018-12-27 NaN
2018-12-28 NaN
2018-12-29 NaN
2018-12-30 NaN
2018-12-31 NaN
我该如何实现?
答案 0 :(得分:1)
一个比较冗长的方法适用于您更长的2018年假期示例:
# Label each holiday and the following block of non-holiday days with
# a unique integer on which to group
df['grouper'] = df['is_holiday'].notnull().cumsum()
# Get days after last holiday, with each holiday as 0
df['aft'] = df.groupby('grouper').cumcount()
# Get days before next holiday. The + 1 is needed because
# cumcount(ascending=False) assigns 0 to the last row
df['bef'] = df.groupby('grouper').cumcount(ascending=False) + 1
df['days_to_holiday'] = df[['aft', 'bef']].min(axis=1)
# Wherever we chose a value from the "days after last holiday" column,
# multiply that value by -1
df.loc[df['bef'] == df['days_to_holiday'], 'days_to_holiday'] *= -1
# Get a boolean mask of days far away from holidays which we
# want to set to NaN
mask = df['is_holiday'].ffill(limit=5).bfill(limit=4).isnull()
df.loc[mask, 'days_to_holiday'] = pd.np.nan
df = df[['dates', 'is_holiday', 'days_to_holiday']]
# Spot check
df.iloc[40:60]
dates is_holiday days_to_holiday
40 2018-02-10 NaN NaN
41 2018-02-11 NaN NaN
42 2018-02-12 NaN NaN
43 2018-02-13 NaN NaN
44 2018-02-14 NaN NaN
45 2018-02-15 NaN 4.0
46 2018-02-16 NaN 3.0
47 2018-02-17 NaN 2.0
48 2018-02-18 NaN 1.0
49 2018-02-19 Family Day 0.0
50 2018-02-20 NaN -1.0
51 2018-02-21 NaN -2.0
52 2018-02-22 NaN -3.0
53 2018-02-23 NaN -4.0
54 2018-02-24 NaN -5.0
55 2018-02-25 NaN NaN
56 2018-02-26 NaN NaN
57 2018-02-27 NaN NaN
58 2018-02-28 NaN NaN
59 2018-03-01 NaN NaN
请注意,在一年中的最后两天(2018-12-30
和2018-12-31
),此解决方案将从节礼日起开始计数,并开始将计算为< / em> 2019年元旦。这对我来说似乎是正确的,但我认为值得一提的是,它在解决方案中是偶然发生的:
df.tail(15)
dates is_holiday days_to_holiday
350 2018-12-17 NaN NaN
351 2018-12-18 NaN NaN
352 2018-12-19 NaN NaN
353 2018-12-20 NaN NaN
354 2018-12-21 NaN 4.0
355 2018-12-22 NaN 3.0
356 2018-12-23 NaN 2.0
357 2018-12-24 NaN 1.0
358 2018-12-25 Christmas Day 0.0
359 2018-12-26 Boxing Day 0.0
360 2018-12-27 NaN -1.0
361 2018-12-28 NaN -2.0
362 2018-12-29 NaN -3.0
363 2018-12-30 NaN 2.0
364 2018-12-31 NaN 1.0