niszetの日記

細かい情報を載せていくブログ

(R小ネタ) RStartHereというリポジトリがある

要するにRStudioのおススメパッケージ群ですが

RStudioのレポジトリには結構色々とパッケージ以外のレポジトリがありますね。今回はその一部です。

RStartHere

github.com

A guide to some of the most useful R Packages that we know about, organized by their role in data science.

ということで、データサイエンス周りで便利なパッケージが列挙されています。とりあえずパッケージ探すときはココを見てみると良いのかも。本当におすすめなものかどうかは使ってみないとわかりませんけどね…。

早速触ってみるか…と思ってみてみたらパッケージ数の多さにそっ閉じしました。いずれ、ね…。

cheatsheets

github.com

ご存知のチートシート集。でも自分あまりチートシート見ないんですよね…

hex-stickers

github.com

例の6角形のパッケージロゴがいっぱい入っています。沢山ありますねぇ…

learnr

github.com

これは文字通りRを勉強できるリポジトリなのだと思うのですが、全部英語なので(当たり前だ)ちょっとキツイなぁ…と。
これも良さげなら布教していきたいですが、そもそも英語で書かれている未知のR言語の説明を読んで理解できるんだったら別に追加のアドバイスとかいらないよね…という気持ちもありますねぇ…。

というわけで、RStudioのレポジトリから何点か気になったモノをピックアップしてみました。 最初の1ページ目から2ページ目くらいは活発に更新されるんですが、それより下は忘れられているのかな…?という感じのパッケージも色々あって、やはりよく使うパッケージを追いかける方が寿命が長くて良いのかなぁ…という気がします。末端Rユーザとしては。

まぁ、そんなことはさておいて、面白そうだったら使ってみる。で、いいじゃないか。とも思いますけどね!

Enjoy!!

(R) 規模が大きくなってきたRmdは階層化して管理する (1回目)

複雑すぎるものは管理できない。管理できるレベルまでシンプルになるように分解する。

業務に関する内容でRによる可視化、ドキュメント化を進めていって、かなり短時間で綺麗に所望の出力が得られるようになったため、今まで見れなかった部分が見れるようになった等、Rの力が存分に発揮されてきました。

そして、これに関連してRmdの構造・構成、パッケージ化など色々と検討してきました。
drakeパッケージによる依存関係の管理についても書いたのですが、一旦原点に返ってknitr側だけでどこまで出来るのか?を考えます。そして、そちらで最適かなという構成が見つかったところでdrakeパッケージによる管理を加えることで、Rを使用したある程度の大規模なドキュメントの生成・管理の環境について考えてみようと思います。

タイトルにもあるように、長大で複雑になってしまったドキュメントの整備は非常に大変です。出来るは出来るんですが、苦痛。
ドキュメントの作成も当然、業務のうちではありますが、ドキュメントを作ることだけが業務ではないし、そもそも構造が複雑で全部読み解かないといけない…的な時間が多いというのはあまりうれしいものではないですよね(はやく帰って🍺を飲もう)

このあたりが動機になります。確実に、しかし手間を減らしわかりやすく、短時間で出来るようにしよう、ということです。

RMarkdown の chunk に 別のRMarkdown を child として使う

さて、ある程度RMarkdownの分量が増えてきた場合の対応策として、chunk部分を別のRMarkdownとして切り出して、子RMarkdownとして使う方法があります。

調べると日本語の記事もヒットします。🐘さんだー!

https://qiita.com/kazutan/items/72276e204944b191c5d5qiita.com

大仏様だー!

www.slideshare.net

そして、先日発売されたこちらですね。おススメ。

www.kyoritsu-pub.co.jp

あ、これ話それる奴だ。これはまたどこかで書きます。子RMarkdownの話を続けます。

子RMarkdownを使うメリットは、分割して小さな単位で管理できることですね。以前、外部の.Rファイルからチャンクを抜き出して使用する、などをしていましたが、どのチャンクがどのファイルにあったのかがわからなくなり、破たんしました。その時は処理部分を全てパッケージ化し、RMarkdownのchunkでそれを呼び出す形を取りました。

この辺りの顛末は末尾のリンクにまとめてあります。

これで、複雑な構造をそれぞれのRmdに分解したことで管理が容易になってめでたしめでたし…なのですが

変数のグローバル汚染問題

この子Rmdを使用する場合でも、ちょっとした問題があります。それは、親のRMarkdownと子のRMarkdownは同じ環境にいます。
どういうことかというと、親RMarkdownに

\```{r}
print("親で代入")
a <- 1
\```

\```{r child="child.Rmd"}
\```

\```{r}
print("親で表示")
a
\```

というチャンクたちを作り、

子RMarkdown(child.Rmdというファイル名で作成)に

\```{r}
print("childで代入")
a <- 10
\```

というチャンクを作り、親側でknitを実行すると、

f:id:niszet:20180514231335p:plain

のように表示されます(チャンクオプションを何も指定していないデフォルト動作の場合)

ということで、親RMarkdownと子RMarkdownの環境は地続きになっていて、子の方で修正や削除をすると、親側の動作に影響があることになります。これは子RMarkdownを挿入する位置によって(つまり、親RMarkdownのchunkの場所によって)動作が異なる原因となり、避けたいところです。

しかし、チャンクオプションとしてchildを渡した際にはこれをどうにかする方法はなさそうです1。 しかし、このchildチャンクオプションに対応した関数が存在し、そちらでは環境を渡すことによって親RMarkdownと子RMarkdownの環境を分離することが出来ます。

実際にやってみます。親側だけ下記のように修正します。

\```{r}
# 親で代入
a <- 1
envir <- new.env()
envir$a <- a
\```

\```{r}
# 子に環境を渡す
knitr::asis_output(knitr::knit_child("child.Rmd", envir=envir, quiet=TRUE))
\```

\```{r}
# 親で表示
a
\```

で、実行結果はこんな感じ。

f:id:niszet:20180514235359p:plain

これで、子環境で変数をうっかり修正してしまっても、親側では影響をうけなくなりました。めでたしめでたし。

追記

これについて、なんと@kohskeさんからご指摘をいただきました。

と、上記のコードでは明示的に変数を子Rmdの環境に与えていますが、子Rmdの環境の親環境が呼び出し元の親Rmdの環境なので、Rは指定された変数が自分の環境に存在しない場合は親の環境を探しに行くので、この場合は親Rmdの環境を探しに行って、そこで見つけることになります。よって、明示的に環境中に変数を与えなくても子Rmdから変数にアクセス可能、ということになります。

これを回避するには、ということで

のように、呼び出し元の親Rmdの環境を飛び越えるようにするために、new.env()parent引数(親となる環境を与えるための引数)にparent.frame()と、呼び出し側である「親Rmdの親」の環境を与えることで、変数を探索する際に親Rmdを飛び越えて探すようになります。階層が深くなったり、ライブラリの読み込み順に起因する環境ツリーの階層依存などは回避できませんが…

後者の、ライブラリ読み込み順などはAtsushiさんのコメント、

のように、共通のsetupチャンクを使用する、ということで回避できます。この辺りを階層Rmdで本気でやるには既に読まれていたら読まないようにする、などの処理が入って煩雑にはなっていきますが…。実際に、自分は既にsetupは別のsetup.Rmdの形にして分離してあります。最終的には一番上のRmdは構造だけを持っていて、データは(文章であっても)持っていてほしくないんですが、そこまでたどりつけていない…。

さらにさらに、🐘さんからも、

と、bookdownのことを教えていただきました。章ごとに管理する、などの際にbookdownでは環境をうまく使い分けているようなのですが、まだ実際に使っていないので感覚がわからず。薄い本作りたいし、bookdownもやっていこう💪

次回以降

さて、これだけだとあまり恩恵を感じないかもしれません。というか、コードの説明もあまりしていませんしね。
現在進行形で階層RMarkdownの効率的な作成方法については色々実験中なので、「これはもう硬いかな…」という部分は不定期に放流していこうかなと思います。気が向いたときにね…。

過去記事

過去、処理部分をパッケージにして分離するとか、chunkを他から読んでくるとかしていました。
このあたり、どれがベストかは規模とか、Rmdで進めてきたかRのコードで進めてきたのか、色々状況によると思います。
ただ、規模が大きくなってきたら単一のRmdで管理するのは結構きついです。きついですが、RStudio IDEの支援機能の、「未定義の変数を使用した」などのチェックはひっかけやすくなるので、下手な分離方法をとるくらいならば1つにまとめた方が良いケースもあるかと。これも人依存かもしれません(私は上にも書いたように、適当にチャンクを分離したりしたのでファイルが見つからなくなったりしましたねぇ…)

niszet.hatenablog.com

niszet.hatenablog.com

niszet.hatenablog.com

niszet.hatenablog.com

niszet.hatenablog.com

頑張っていきましょう。

Enjoy!!


  1. あったら教えてください。

(R) 今までに更新があったbaseの関数たちを確認できる…らしい(メモ)

割とTwitterで情報拾うことが多い昨今。

↑のtweetのリンク先の

にて確認できます。こうしてみると、結構色々変更されているんだなぁ、と。

まぁ、普段は特段気にしなくて良いんじゃないかなって思いますけどね…。古いコードと出会ったときには確認してみると良いのかな1。 Enjoy!!


  1. 僕は新参なのでそういう遺産コードは持っていない。

(R) janitorパッケージを使って集計を楽に行おう (janitorパッケージを使う 第2回)

tabyl() まわり

便利な前処理(というか、データクレンジング)に関する関数が揃ったjanitorパッケージですが、他にも集計関係の関数が多々含まれています。

clean_names()で書いた通り、日本語の文字は全て分割されて_が付与されてしまう挙動があるので、その処理が噛んでしまうものは使えないのですが、いくつかは日本語列名でも対応できています。

やってみます。1次元のベクトルの場合。

天気 <- c("晴", "晴", "晴", "雨", "雨", "晴", "曇")

tabyl(天気)
 天気 n   percent
   雨 2 0.28571434 0.57142861 0.1428571

データ中にNAがあっても対応できて、NAを分母に含んで割合を計算した列とNAを除いた割合を計算した列が作られます。

天気 <- c("晴", "晴", "晴", "雨", "雨", "晴", NA)

tabyl(天気)
#>  天気 n   percent valid_percent
#>    雨 2 0.2857143     0.3333333
#>    晴 4 0.5714286     0.6666667
#>  <NA> 1 0.1428571            NA

2次元も可能。3次元も対応できるようです(試してない)

df <- data.frame(天気 = c("晴", "晴", "晴", "雨", "雨", "晴", "曇"), 進捗=c("ダメ", "良い", NA, "良い", "良い", "ダメ", "ダメ"))


janitor::tabyl(df)

#>  天気 ダメ 良い NA_
#>    雨    0    2   0
#>    晴    2    1   1
#>    曇    1    0   0

NAは列名にする際にNA_にするようです。

この結果を割合にすることも可能。

janitor::tabyl(df) %>% adorn_percentages()

#>  天気 ダメ 良い  NA_
#>    雨  0.0 1.00 0.00
#>    晴  0.5 0.25 0.25
#>    曇  1.0 0.00 0.00

タイトルというか、列方向の項目名をつけてくれます。

jtab %>% adorn_title()
#>       進捗         
#>  天気 ダメ 良い NA_
#>    雨    0    2   0
#>    晴    2    1   1
#>    曇    1    0   0

合計を追加。

#> jtab %>% adorn_totals(where = "row")
#>   天気 ダメ 良い NA_
#>     雨    0    2   0
#>     晴    2    1   1
#>     曇    1    0   0
#>  Total    3    3   1

さて、ここで列方向ですが、

jtab %>% adorn_totals(where = "col")
#> Error in FUN(X[[i]], ...) : object 'ダ_メ' not found

でコケます。clean_namesを噛んでいるためでしょう。この場合、根本的にはデータ自体を書き換えないといけないのがちょっと厳しさを感じますね。

応急処置的に、列名を書き換えてみます。

jtab <- janitor::tabyl(df)
colnames(jtab)<-c("weather", "bad", "good", "NA_")
jtab %>% adorn_totals(where = "col")
#>  weather bad good NA_ Total
#>       雨   0    2   0     2
#>       晴   2    1   1     4
#>       曇   1    0   0     1

出来ました。tabyl()で処理した結果はtabylクラスとdata.frameクラスであり、data.frameに対して出来ることは何でもできます。View()で見た場合はdata.frameとしての表示になります。

 class(jtab)
#> [1] "tabyl"      "data.frame"

なので、適宜上記のように対応するのが苦労が少ないのかな…。あまり良い方法ではないですが、集計自体をデータの確認で使う場合はいけるところまで行った方が楽かなと。

集計結果が最終成果物であれば、データ自体を直しておいた方が良いとは思いますが…。

引数によるオプションの指定も含めてまだまだ色々できますが、長くなってきたのでこのあたりで。

日本語まわりの処理がうまくいけば、janitorパッケージはかなり有用なパッケージになると思います。現時点でも十分強力だと思いますけどね。特にdirtyなexcelファイルを渡されたときのクレンジングからのピボットテーブルのような手軽な集計までがRで閉じるのはかなりQOLが上がると思います。アンケート調査等をされている方は特に使えるのではないのかなーと思っています。

日本語周り、どうすればよいのか現在調査中…(最終的にstringiパッケージに行きついて辛い気持ちになっている)

Stay tuned.

Enjoy!!

(R) drakeパッケージを頑張って使う…(必要は今はないよ…)

早くCRAN版が更新されてほしい…

さて、drakeパッケージですが、現状ではまだまだ問題があって色々と使いにくいところがあります。 前回あんなに推したのにね!

niszet.hatenablog.com

filterとの相性が悪い。

たとえば、下記のコードをRmd中のchunkとして使用すると正しくknitされてhtmlなりwordなりが生成されます。

plan <- drake_plan(
  ss = summary(cars),
  cc = cat("hoge"),
  strings_in_dots = "literals",
  iris_ = readr::read_csv("iris.csv"),
  # 以下のコメントを外すと動作しない 
  # iris_0 = iris_ %>% dplyr::filter(.$Sepal.Length > 3),
  iris__ = iris_ %>% mutate(hoge = Sepal.Length) %>% mutate(hoge2 = ifelse( stringr::str_detect("^s", string = .$Species), "h", "j")) %>%
    ggplot()+geom_point(aes(x=Sepal.Length, y=Sepal.Width))
)
config <- drake_config(plan)
make(plan)
vis_drake_graph(config)
readd(ss)
readd(cc)
readd(iris_)

これを実行するとこんな感じのdependency graphが作れます。

f:id:niszet:20180509002357p:plain

filterに関してissueを漁ると、例えば以下のようなものが見つかります。

github.com

どうやらCodeDependsパッケージが悪いらしい。ということで以下のコマンドで入れてみようとする。

devtools::install_github("duncantl/CodeDepends")

が、これをやろうとすると以下のようなエラーが出ます。

ERROR: dependency 'graph' is not available for package 'CodeDepends'

なんなのさ…とCRANの方を見に行くと、

https://cran.r-project.org/web/packages/graph/index.html

Package ‘graph’ was removed from the CRAN repository.

Formerly available versions can be obtained from the archive.

This package is now available from Bioconductor only, see <http://www.bioconductor.org/packages/release/bioc/html/graph.html>.

と、Bioconductorに行けと言われるので行ってみます。

www.bioconductor.org

中段にある2行を実行します。

source("https://bioconductor.org/biocLite.R")
biocLite("graph")

そうするとなんか入りますね

Bioconductor version 3.6 (BiocInstaller 1.28.0), ?biocLite for help
A new version of Bioconductor is available after installing the most recent version of R; see
  http://bioconductor.org/install

現状だとgraphの依存パッケージがCRAN上でバイナリがないため、コンパイルする?って聞かれるので対象は全部コンパイルしてでも最新のものを入れます。

graphとその依存パッケージが無事にはいったら改めて

devtools::install_github("duncantl/CodeDepends")

を実行します。

*** arch - i386
 警告:  replacing previous import 'graph::addNode' by 'XML::addNode' when loading 'CodeDepends'
 警告:  replacing previous import 'graph::plot' by 'graphics::plot' when loading 'CodeDepends'
*** arch - x64
 警告:  replacing previous import 'graph::addNode' by 'XML::addNode' when loading 'CodeDepends'
 警告:  replacing previous import 'graph::plot' by 'graphics::plot' when loading 'CodeDepends'

こういう警告が出ますが、まぁgraphわざわざ入れましたからね…。無視します。

このあと、RをRestartして、最初のfilterのコメントアウトを外すと動くはずです。

が、なんか最初typoしていたみたいなので、上記のコードは本当は動いたのかも。ただ、別の環境でfilterを使用して動かないことはあったので、それを回避するには上記の一連の作業が必要です。面倒くさいですね。

それでもダメな時がある。

ごくまれにですが、filter(.$列名 == 条件)のように.$を列名の前につけないとダメな時があります。というより、↑のコードも外すとなりますね。readd()していないのでエラーになりませんが。
これはvis_drake_graph()で対象の列が謎のMissing扱いのObjectになっていることから分かります。一応このときもdrake_config()make()は通るはずで、readd()しなければ問題は起こらないはずです。filter()を使用したplanを作ったらまずdependency graphを確認しておくと良いと思います。

htmltools$tags などはダメっぽい。

Rmd中にdrakeのコードを埋め込んだり、knitrのoptionを受け取ったりすることは問題なくできるようですが、htmltoolsでhtmlのタグを返してRmd中に埋め込んでみた箇所は動きませんでした。これはまだ深追いしていないので良く分からないけど。

結論

drakeパッケージを本格的に使うにはまだ早すぎる。

が、前処理部分の処理の要不要を判断してskipしてくれているような気がするので、knit時の実行時間がかなり短縮されている気がします。うまく使いこなせれば便利なんですがねぇ…。安定したCRAN版が出るまでは本番環境で使用するのは避けた方が良いかな、と思います。今触っておくのも楽しいとは思いますけどね!

他にも注意すべき点が何点かあって、drakeの関数の引数として与えるので代入は<-ではなくて=であるんだけど、当然その外は普通のRのコードなので<-で与えるべきとか、""を使うときはオプションを設定するだとか、dependencyはチェックしてくれるけどソースの違いはgitで管理しないといけないとか、同名の変数は定義できないので、順に足しているようなコードの場合はそれぞれを別名に書きなおさなくてはいけないとか。

暗黙の依存性は多分上記で解決しているはずなんだけど、発生した場合は良く分かりませんね。Rmd中で書いたコードのdiagnoseがグローバル環境で参照できるのも謎。.drake/を読みに行ってるからなんだろうか。

長大なコードの場合、dependency graphも複雑になってよくわからなくなります。たぶんこれはRmdを階層化して、その階層構造そのものをdrakeで管理、個別のRmdもdrakeで管理、依存関係は別途レポートしつつRmdの出力はhtmlなど所望の形に…という感じかなーと思うのですが、それをやるなら機能群としての何かしらのパッケージの形態が良いのかな、と。

RStudio IDEは階層構造をもったRスクリプト、Rmdなどの管理にはあまり強くないので、ドキュメントの規模が大きくなってきた際にそれを管理する方法は現状ではベストと言えるものはないのかなと思います。が、drakeはそれを解決するための答えの候補なのではないかなと思って注目している次第です。

まぁ実際は前処理コードが長いので、差異がなければ処理をスキップしてくれるようになってくれるだけでdrakeの価値があると僕は思っている(つまり、依存関係の管理ではなくてknitの処理時間の短縮に興味がある。中間結果を保存しているので1度実行すればそのチャンクをeval=FALSEすればよいのだが、それを毎回行うのは大変なのだ)

取り留めない感じになってきましたのでこのあたりで。

Enjoy!!

(R) 僕たちはいつだってpipeを使いたい

あるいは自作パッケージ中で外のパッケージの関数を使うための方法?

先日、キャプテンと羽鳥のやり取り、

とその元になった記事

petermeissner.de

があったので、忘れないようにメモ。

最近のパッケージは他のパッケージで使われている関数をそのままexportしているものが結構ある。と思う。

pipe、'%>%'、つかいはじめるまでは取っつきにくいものの、使い慣れてくるともうこれがない世界に戻れない…という気持ちになったりならなかったりと噂のアイツですが、多くのパッケージがpipe friendlyになっていくなかで自作のパッケージもやっぱり対応したいし、自分のパッケージ内でも%>%が使えるようにしたいし、アタッチしたらコンソール上で'%>%'を使えるようにしたいですよね1。 その答えが参照している記事なのですが、 Hadleyが呟いているように、 usethis::use_pipe()を使うことで記事中で書かれているコードとほぼ同等のものが生成されます。ロード順が気になる場合はファイル名は変えた方が良いですが。

usethisパッケージにはこの他にも便利な関数が揃っていて、使えない宗教的な理由等がなければ積極的に使った方が良いと思います。ちなみに、先日のggbodeパッケージでもggplot2::aesを使いたくて同じようなことをしていました。

ひとつ注意なのは、最後のNULLで、Rのコードが含まれていない(すべての行がコメントとか)場合はパッケージのビルド時に無視されるようで、私はコレで半日ハマっていました。実質NULLは何もしないので副作用等もなく安心です。usethis::use_pipe()ではこの点がもちろん考慮されているので、他の関数を使いたいなぁ~というときもこのファイルをコピペして適宜修正するのが良いかと思います。

しかし、この方法を使うためにはroxygen2にNAMESPACEの管理を任せる必要があり、それはCtrl+Shift+Dによるドキュメント生成を有効にする必要があることを意味していて、そのためにはRStudio IDEの設定を少し変更する必要があります。

なので、usethisを使った📦作成についてはちょっと別記事でまとめようかな…。たまにしか使わないのでいつも「あれ?動かねぇ…」となるので、そろそろまとめ時。

というわけで、Stay tuned!

Enjoy!!


  1. いちいちlibrary(magrittr)したくないのですよ~

色々行ってきた

タイトルが雑ですが、コミティア→コミックZIN→絵師100人展→ヨドバシでした。

5/5は午前中にubuntuを18.04にし、病院行こうと思ったらGWなので休んでいて断念、コミティアに行く、秋葉原に行く途中で迷いつつも秋葉原に行ってコミックZINさんで同人誌買い足し、絵師100人展に行く、ヨドバシでHHKBとVOICEROIDを購入するという、歩くと財布が薄くなる(実際にはカードだから平気(平気じゃない))という生活でした。

Ubuntu 18.04 LTS

良いですね。今日5/6もいじってます。R環境、python環境まわりを。cudaまで終わった。が、keras動かせねぇと意味ないのだよ…。

コミティア

去年は技術書典には行ったものの、それ以外の創作系は冬コミから行ったことがありませんでしたので、久々のイベント…。
14時くらいに着くように行ったのですが、それでも結構人がいましたね。そして、暑い。夏コミ行ったことないけど修羅場になるんだろうな…。

目的はちゃんと果たした。会場にいたらしい電子回路工作勢の方とはエンカウントできませんでしたが…(私自身は全然工作してません、はい)

次はMFT2018ですかねー。楽しみ。

まぁ、それ以前に何か工作イベントがあれば、そこでお会いできるかもしれませんね~

時間の許す範囲で会場をぐるっと回ってきましたが、この大きな会場に、これだけの人が思い思いに自分の創作物を持ち寄って…という場と空気が最高でした。もっと早く行くべきだったよな…。
そして、5-6か所刺さる絵柄があって、思わず購入しそうになりましたが…無限に沼が増えるのでやめておきたい。電子化されていて、作者さんにお金が入る仕組みで、なんとか(絵は無限に増えて場所を取るので。本は…本もだけどさ……)

コミックZIN

コミティアの会場でZINさんの中の人とお話して、技術書典の本は順次はいってきそうということで、とりあえず行ってきた()
結果、気になっていた2冊と見たことなかったのを1冊。買いすぎじゃない?

また来月くらいに行ってみましょうかねー

ヨド

HHKB買ってしまいました。既に東プレ2台あるのにね…。まぁ良いのだ。 そして、VOICEROID2を買ってきました。ゆかりさんがいなかったので茜・葵ちゃんを。早速触ってみましたが、感情表現対応ということでパラメータ振ってみてましたが、聞き比べたらわかるんだけど…イントネーションいじらないとわからんかもな。あと、関西イントネーションがわからなくて標準語だけで作りそうです。

一応個人向けの商用ライセンスがあるんですね。

VOICEROID 個人向け商用ライセンス|製品情報|AHS(AH-Software)

これ、先日のインフラ勉強会がきっかけの1つになってます。結構自然になるもんだなーって思ったので。
ボカロから調整も出来るんですが、パラメータが多すぎてねぇ…。その点、こちらは喋ることに特化しているので簡単にそれらしく喋ってくれるのが良いですね。

勉強会とかだと商用ライセンスには触れないと思うんだけど、半導体のお勉強とかのコンテンツ作るなら…考えるかな。

まぁコレでしばらくの砂漠生活を乗り切れるのではないかと思います…。何せ次の祝日は7月の後半ですからね…HAHAHA...

乗り切ろう。