R言語における日本の祝日判定
Rにおいて日本の祝日を判定する方法を解説します。
『内閣府:「国民の祝日」について』で提供されている祝日のデータを用いて祝日判定を行います。
いままでNipponパッケージを使って祝日判定をする方法を紹介してきました。しかしNipponパッケージが2019年7月現在、使用できなくなっています。
祝日判定をするだけでしたら、比較的短いコードで実装が可能です。この記事ではパッケージを使わずに祝日判定を行います。
なお拙著『時系列分析と状態空間モデルの基礎:RとStanで学ぶ理論と実装』においてもNipponパッケージを用いています。
こちらの書籍をお持ちの方は、Nipponパッケージを使う代わりに、この記事で紹介されている方法を用いてください。
『内閣府:「国民の祝日」について』で提供されているデータを使用しています。こちらのページのURLが変更されてコードが動かなくなった等の問題があれば、コメントなどでお知らせいただけますと幸いです。
コードはすべてGitHubで公開しています。
当方で簡単な動作確認を行いましたが、結果を保証するものではありません。参考程度にお使いください。
何か問題があれば、コメントなどでお知らせいただけますと幸いです。
目次
1.祝日判定をする関数の基本的な使い方
ネットに接続されていることを前提として、祝日判定をする関数の基本的な使い方を見ていきます。
関数の名前はis.jholidayです。これはNipponパッケージの関数名に合わせています。
基本的な使い方
(2020年10月2日追記)
下記の『祝日判定関数:is.jholiday』において、文字コードが指定できるように修正しました。
ただしデフォルト引数として「 “CP932″」を与えているので、単に「is.jholiday(target_date = target_date)」とするだけで動作する点は今までと同じです。
(追記終わり)
関数はWeb上で公開されているので、以下のコードを実行するだけで、いつでも『祝日判定関数:is.jholiday』が使えるようになります。
# 関数の読み込み source("https://raw.githubusercontent.com/logics-of-blue/website/master/010_forecast/20190714_R%E8%A8%80%E8%AA%9E%E3%81%AB%E3%81%8A%E3%81%91%E3%82%8B%E6%97%A5%E6%9C%AC%E3%81%AE%E7%A5%9D%E6%97%A5%E5%88%A4%E5%AE%9A/jholiday.R", encoding="utf-8")
仮に、2019年5月1日から5月31日までの祝日を判定したいと思ったとします。
判定対象となる日付を用意します。
# 祝日判定をしたい日付データ target_date <- seq( from = as.Date("2019-05-01"), to = as.Date("2019-5-31"), by = 1 )
結果はこちら
> target_date [1] "2019-05-01" "2019-05-02" "2019-05-03" "2019-05-04" [5] "2019-05-05" "2019-05-06" "2019-05-07" "2019-05-08" [9] "2019-05-09" "2019-05-10" "2019-05-11" "2019-05-12" [13] "2019-05-13" "2019-05-14" "2019-05-15" "2019-05-16" [17] "2019-05-17" "2019-05-18" "2019-05-19" "2019-05-20" [21] "2019-05-21" "2019-05-22" "2019-05-23" "2019-05-24" [25] "2019-05-25" "2019-05-26" "2019-05-27" "2019-05-28" [29] "2019-05-29" "2019-05-30" "2019-05-31"
is.jholiday関数を使えば、祝日ならTRUE、そうでなければFALSEを返してくれます。
2019年のゴールデンウイークにおける、振替休日を含めた祝日の判定ができました。5月1日から6日までが祝日となっています。
> # 日付において、祝日ならTRUE、そうでなければFALSEを返す > is.jholiday(target_date = target_date) [1] TRUE TRUE TRUE TRUE TRUE TRUE FALSE FALSE FALSE FALSE [11] FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE [21] FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE [31] FALSE
書籍『時系列分析と状態空間モデルの基礎』での使用例
拙著『時系列分析と状態空間モデルの基礎:RとStanで学ぶ理論と実装』をお持ちの方はNipponパッケージを読み込む代わりに、source関数を実行してください。そうすれば、書籍と同じ結果を得ることができます。
p271からp273冒頭までのコードは以下のようになります。
# パッケージの読み込み library(KFAS) library(xts) library(ggplot2) library(ggfortify) library(gridExtra) # Nipponパッケージの代わりに、祝日判定関数を読み込む source("https://raw.githubusercontent.com/logics-of-blue/website/master/010_forecast/20190714_R%E8%A8%80%E8%AA%9E%E3%81%AB%E3%81%8A%E3%81%91%E3%82%8B%E6%97%A5%E6%9C%AC%E3%81%AE%E7%A5%9D%E6%97%A5%E5%88%A4%E5%AE%9A/jholiday.R", encoding="utf-8") # データの読み込み file_data <- read.csv("https://raw.githubusercontent.com/logics-of-blue/book-tsa-ssm-foundation/master/book-data/5-11-sales_data.csv") # xts型に変換 sales <- as.xts(read.zoo(file_data)) head(sales, n = 3) # 日付の抽出 dates <- index(sales) head(dates, n = 5) # 祝日の判定 head(is.jholiday(dates)) ## 以下略(書籍とまったく同じコードでOKです)
関数の仕組みの簡単な解説
当方の作成したis.jholiday関数は以下のようになっています。
長いように見えますが、ほとんどはコメントです。
(2020年10月2日追記)
文字コードが指定できるように修正しました。
is.jholiday <- function(target_date, holiday_source = "https://www8.cao.go.jp/chosei/shukujitsu/syukujitsu.csv", encoding = "CP932", excluded_days = NULL, flag = FALSE) { # 日本の祝日を判定する関数。 # 初期状態では、『内閣府:「国民の祝日」について』というWebサイトで # 提供されている祝日のデータを用いて祝日判定を行う。 # この場合はネット環境が必要。 # # Args: # target_date : 祝日判定の対象となる日付のベクトル # holiday_source : 祝日判定の根拠となる祝日データ # 1列目が祝日の日付、2列目が祝日の名称 # encoding : ファイルの文字コードを指定する文字列 # excluded_days : 除外する曜日のベクトル。その曜日は決して祝日とみなされない # 「月・火・水・木・金・土・日」のいずれかを指定する # flag : TRUEなら、0または1の数値型のベクトルを返す # FALSEなら、論理値型のベクトルを返す # # Returns: # 祝日判定の結果。target_dateと同じ長さのベクトル # 対象となるベクトルを日付型にする target_date <- as.Date(target_date) # holiday_sourceをもとに祝日を取得 holidays <- read.csv(holiday_source, fileEncoding = encoding) colnames(holidays) <- c("date", "holyday_name") holidays$date <- as.Date(holidays$date) # 祝日判定 if(is.null(excluded_days)) { # すべての曜日で判定 result <- target_date %in% holidays$date } else { # 特定の曜日を除外 result <- (target_date %in% holidays$date) & !(weekdays(target_date, TRUE) %in% excluded_days) } if(flag) { # 0または1のフラグにする result <- as.numeric(result) } # 祝日判定の結果を返す return(result) }
処理についてはコメントを参照いただければ、ある程度理解できるかと思います。
『内閣府:「国民の祝日」について』というWebサイトから祝日が記録されたデータを読み込み、その結果と判定対象の日付を『%in%』を使ってマッチングさせています。
やり方はたくさんあるでしょうが、外部パッケージを使わなくて済むので、この方法にしています。
実は特定の曜日を除外したり、0か1のフラグで結果を返したりもできます。この辺りの使い方を次から解説します。
2.祝日判定をする関数の応用的な使い方
ネットに接続できない場合
『内閣府:「国民の祝日」について』というWebサイトが閲覧できればよいのですが、ネットに接続できていないこともあるでしょう。
この場合は、内閣府が提供してくれている祝日が入ったCSVファイルを自分のパソコンにダウンロードしておきます。
is.jholiday関数が実装された『jholyday.R』と、祝日が格納された『syukujitsu.csv』がともに『C:\data_folder』というフォルダにある場合は、以下のようなコードになります。
# 祝日判定関数の読み込み source("C:/data_folder/jholiday.R", encoding="utf-8") # 祝日判定をしたい日付データ target_date <- seq( from = as.Date("2019-05-01"), to = as.Date("2019-5-31"), by = 1 ) # 祝日判定 is.jholiday(target_date = target_date, holiday_source = "C:/data_folder/syukujitsu.csv")
is.jholidayにholiday_sourceという名称で祝日ファイルのフルパスを指定すればよいです。
特定の曜日を除く
日曜日でかつ祝日、という場合は、わざわざ祝日扱いをしたくないときがあります。
日曜日を除いて祝日判定をする場合は『excluded_days = "日"』を指定します。5月1日は水曜日ですね。5月5日(日)がFALSEに変わったのがわかります。
> # 日曜日を除く > is.jholiday(target_date = target_date, + excluded_days = "日") [1] TRUE TRUE TRUE TRUE FALSE TRUE FALSE FALSE FALSE FALSE [11] FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE [21] FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE [31] FALSE
土日をともに除く場合は以下のようにexcluded_daysに曜日のベクトルを指定します。
> # 土日を除く > is.jholiday(target_date = target_date, + excluded_days = c("土", "日")) [1] TRUE TRUE TRUE FALSE FALSE TRUE FALSE FALSE FALSE FALSE [11] FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE [21] FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE [31] FALSE
0か1の祝日フラグを作る
統計モデルなどを構築する際、0か1の祝日フラグがほしいときがあります。
この場合は『flag = TRUE』を指定します。
> # 0か1のフラグで出力 > is.jholiday(target_date = target_date, + flag = TRUE) [1] 1 1 1 1 1 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 [31] 0
拙著『時系列分析と状態空間モデルの基礎:RとStanで学ぶ理論と実装』では、日曜日を除く祝日に対して「1」となるフラグを作成していました。これは、以下のコードで達成できます。
> # 日曜日を除き、0か1のフラグで出力 > is.jholiday(target_date = target_date, + excluded_days = "日", + flag = TRUE) [1] 1 1 1 1 0 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 [31] 0
参考文献
時系列分析と状態空間モデルの基礎: RとStanで学ぶ理論と実装 このブログの管理人が執筆した、時系列分析の入門書です。 時系列分析の基礎から、応用的な分析手法まで解説しています。 サポートページはこちらです。 |
更新履歴
2019年07月14日:新規作成
2020年10月02日:is.jholiday関数において、文字コードが指定できるように修正
source(“https://raw.githubusercontent.com/logics-of-blue/website/master/010_forecast/20190714_R%E8%A8%80%E8%AA%9E%E3%81%AB%E3%81%8A%E3%81%91%E3%82%8B%E6%97%A5%E6%9C%AC%E3%81%AE%E7%A5%9D%E6%97%A5%E5%88%A4%E5%AE%9A/jholiday.R”, encoding=”utf-8″)
target_date <- seq(
+ from = as.Date("2019-05-01"),
+ to = as.Date("2019-5-31"),
+ by = 1
+ )
is.jholiday(target_date = target_date)を実行すると
Error in make.names(col.names, unique = TRUE) : invalid multibyte string at '�Ex’
のエラーが出るのですが。
解決策を教えていただきたいです。
sssu様
コメントありがとうございます。
管理人の馬場です。
返信が遅れて申し訳ありません。
当方で確認したところ、エラーにはなりませんでした。
PCもしくはRやRStudioの設定が原因であるようです。
エラーメッセージを見ると、文字コードの問題のようです。
例えば、以下のコードを実行してからもう一度is.jholidayを再実行すると、うまくいくかもしれません。
options(encoding="Shift_JIS")