シーズンを取得する方法と、日付範囲がパンダとの米国の休日に該当する場合はどうなりますか?
date_xとdate_yという名前の2つの列を持つパンダデータフレームがあります。date_xの季節(冬、春、夏、または秋)を別の列に表示して、date_yを除く日付の範囲で休日が該当するかどうかを確認したいと思います。1年を数日に分割することで季節を変えたいくつかの潜在的な解決策を見てきましたが、それをうまく機能させることができないようです。私はまだパンダが何ができるかを考えています。私が直面しているもう1つの問題は、毎年変わるイースターのような休日をどのように説明するかです。どんな助けでも本当にありがたいです。
私もこのソリューションを機能させるために遊んだことがありますが、今日の日付ではなくdate_xで機能する新しい列を作成するためにそれを適応させる方法を理解できません
以下は私が目指していることのイメージです。

回答
複数の休日に及ぶだけでなく、複数の季節に及ぶ日付のデータフレームがあるとします。
Date_x Date_y
0 2020-12-22 2021-01-01
1 2020-06-20 2020-07-11
3 2020-02-11 2020-03-27
4 2020-05-22 2020-06-27
1.Season
と2を取得するためにHoliday
:
- 季節をカスタマイズするためにあなたが共有したリンクを構築しました
- 私は「サードパーティ」ライブラリを避けようとし
USFederalHolidayCalendar
、pandas
holiday
ライブラリからを使用することを選択しました。なぜなら、それがより信頼できると思ったからです。しかし、私は休日の図書館についてはあまり経験がありません。また、calendars
パンダライブラリから使用できるものは複数あります。そこから、作成したget_season(x)
andget_holiday()
関数を使用しました。前者については、質問のリンクを参照し、後者については、リスト内包表記を使用して、作成したholidays
データフレームからデータフレームに休日を取り込みます。
from pandas.tseries.holiday import USFederalHolidayCalendar
from datetime import datetime
import pandas as pd
cal = USFederalHolidayCalendar()
holidays = (pd.DataFrame(cal.holidays(return_name=True), columns=['Holiday'])
.reset_index()
.rename({'index': 'Date'}, axis=1))
holidays['Date'] = pd.to_datetime(holidays['Date'])
df= pd.DataFrame({'Date_x': {0: '2020-12-22', 1: '2020-06-20', 2: '2020-02-11', 3: '2020-05-22'},
'Date_y': {0: '2021-01-01', 1: '2020-07-11', 2: '2020-03-27', 3: '2020-06-27'}})
df['Date_x'] = pd.to_datetime(df['Date_x'])
df['Date_y'] = pd.to_datetime(df['Date_y'])
Y = 2000 # dummy leap year to allow input X-02-29 (leap day)
seasons = [('Winter', (date(Y, 1, 1), date(Y, 3, 20))),
('Spring', (date(Y, 3, 21), date(Y, 6, 20))),
('Summer', (date(Y, 6, 21), date(Y, 9, 22))),
('Fall', (date(Y, 9, 23), date(Y, 12, 20))),
('Winter', (date(Y, 12, 21), date(Y, 12, 31)))]
def get_season(x):
x = x.replace(year=Y)
return next(season for season, (start, end) in seasons
if start <= x <= end)
def get_holiday():
return pd.DataFrame([(h,y,z) for (h,d) in zip(holidays['Holiday'], holidays['Date'])
for (y, z) in zip(df['Date_x'], df['Date_y']) if y.date() <= d.date() if d.date() <= z.date()], columns=['Holiday', 'Date_x', 'Date_y'])
s1 = df['Date_x'].apply(lambda x: get_season(x))
s2 = df['Date_y'].apply(lambda x: get_season(x))
df['Season']= [', '.join(list(set([x,y]))) for (x,y) in zip(s1,s2)]
dft = get_holiday()
dft = dft.groupby(['Date_x', 'Date_y'])['Holiday'].apply(lambda x: ', '.join(list(x)))
df = pd.merge(df, dft, how='left', on=['Date_x', 'Date_y'])
df
Out[32]:
Date_x Date_y Season Holiday
0 2020-12-22 2021-01-01 Winter Christmas, New Years Day
1 2020-06-20 2020-07-11 Summer, Spring July 4th
2 2020-02-11 2020-03-27 Spring, Winter Presidents Day
3 2020-05-22 2020-06-27 Summer, Spring Memorial Day
以下のようなものをお探しだと思います。このソリューションの一部では、ここで提供される回答を使用していることに注意してください。
あなたはあなたの排他的な要件を説明するために調整しなければならないかもしれません、しかしこれはあなたに考えを与えます。
import pandas as pd
import numpy as np
import holidays # pip install holidays
from datetime import date, datetime
us_holidays = holidays.UnitedStates()
Y = 2000 # dummy leap year to allow input X-02-29 (leap day)
seasons = [('winter', (date(Y, 1, 1), date(Y, 3, 20))),
('spring', (date(Y, 3, 21), date(Y, 6, 20))),
('summer', (date(Y, 6, 21), date(Y, 9, 22))),
('autumn', (date(Y, 9, 23), date(Y, 12, 20))),
('winter', (date(Y, 12, 21), date(Y, 12, 31)))]
def get_season(dt):
if isinstance(dt, datetime):
dt = dt.date()
dt = dt.replace(year=Y)
return next(season for season, (start, end) in seasons
if start <= dt <= end)
def get_holiday(data):
return ",".join([us_holidays.get(x) for x in us_holidays[data["Date_X"] : data["Date_Y"]]])
np.random.seed(0)
rng_x = pd.date_range('2020-12-22', periods=365, freq='D')
rng_y = pd.date_range('2020-12-26', periods=365, freq='D')
df = pd.DataFrame({ 'Date_X': rng_x, 'Season_X': "", 'Date_Y': rng_y, 'Season_Y': ""})
print(df.head())
df['Season_X'] = df["Date_X"].apply(get_season)
df['Season_Y'] = df["Date_Y"].apply(get_season)
print(df.head())
df['Holiday'] = df.apply(get_holiday, axis=1)
print(df.head())
出力:
Date_X Season_X Date_Y Season_Y Holiday
0 2020-12-22 winter 2020-12-26 winter Christmas Day
1 2020-12-23 winter 2020-12-27 winter Christmas Day
2 2020-12-24 winter 2020-12-28 winter Christmas Day
3 2020-12-25 winter 2020-12-29 winter Christmas Day
4 2020-12-26 winter 2020-12-30 winter
列を日時型に変換し(まだ変換されていない場合)、2つの新しい空の列を作成します。
df.Date_x = pd.to_datetime(df.Date_x)
df.Date_y = pd.to_datetime(df.Date_y)
quarter
datetime Seriesの属性に気づいたら、Season列の追加は簡単です。
df['Season'] = df.Date_x.dt.quarter.map({1: 'Spring', 2: 'Summer', 3: 'Fall', 4: 'Winter'})
休日は明らかにもう少し複雑です。空の列から始めます。
df['Holiday'] = ''
イースターは特別なものです。最初にそれを処理しましょう。Pandasにはそれが組み込まれていますが、独自の休日ルールを定義することもできます。
easter = df.Date_y - pd.tseries.offsets.Easter()
それはあなたに以前のイースターを与えますDate_y
(私は使うことができましたがDate_x + Easter()
、あなたはそれを排他的にしたいと言いましたDate_y
)。次に:
df.loc[df.Date_x < easter, 'Holiday'] = 'Easter'
これにより、休日が含まれる行に「イースター」が配置されます[Date_x, Date_y)
。
残りの休日の休日ルールを作成するための演習として残しておきます。それに関するいくつかのアドバイスがあります:パンダ時系列ホリデールールオフセット