思っちゃったんだからしょうがない

統計学を学ぶ傍でひっそりとやっていきます。 #statistics #R

九九、五の段より上は覚えなくて良い説

突然ですが、中京テレビで放送されている太田上田という番組でくりぃむしちゅーの上田さんがこんなことを言っていました。

九九は五の段より上は覚えなくても計算ができる!

番組が気になる方はHuluで全話視聴できます! chuun.ctv.co.jp

その方法は?

さて、気になる計算方法ですが、まず5より大きく10よりも小さい二つの整数を考えます。5 \lt a,b \lt 10

上田さんが紹介した方法では,まず片手それぞれで a, bを指を折って数えていきます。5より大きいので5から先は指を立てていくようにして数えましょう。
親指から指を折って数えていき、6以上は小指から立てていくようにしましょう。こうすると7ならば3本の指が折れていて2本の指が立っているという具合です。
二つの数をそれぞれの手でこのように数えた後、

  1. 立っている指を足して10倍する
  2. 折れている指同士を掛け算する
  3. 1と2を足す

すると所望の掛け算の結果が求まります。

 9 \times 7を求めてみます。

  • 右手で9を数えます。親指が折れていて、その他の4本の指は立っています。
  • 左手で7を数えます。親指、人差し指、中指が折れていて、そのほかの2本の指は立っています。
  • 立っている指の数を足しましょう\rightarrow 4+2=6.これを10倍して$60$です。
  • 折れている指同士を掛け算しましょう\rightarrow 1 \times 3 = 3
  • これらを足しましょう60 + 3 = 63 (= 9 \times 7)

なぜか

そこまで難しいことではなく、結局これはa = 10 - a'という表現に直して計算していることと同じになります。いまbの方もb=10-b'としましょう。すると

\begin{aligned}
a \times b & = (10 - a') \times (10 - b') \\
& = 100 - 10 a' - 10 b' + a' \times b' \\
& = 10 (10 - (a' + b')) + a' \times b'
\end{aligned}

最後の式の第1項が立っている指の数の10倍に対応し、第2項が折れている指同士の掛け算に対応しているわけです。

ちょっとまった

両方とも5より大きい場合はOKだし、両方とも5以下の場合もOKですが、片方が5より大きい場合はどうなるのでしょうか。 先ほどと同様に考えていきます。ここではaを大きい方としましょう。

\begin{aligned}
a \times b &= (10 - a') \times b \\
&= 10 b - a' \times b' 
\end{aligned}

この場合、 1. 小さい方の数を10倍したもの 2. 折れている指と同士の掛け算 3. 1 - 2 をする

という具合になります。両方5より大きい場合と計算の仕方が結構変わってきますね。

結論

どちらかが5より大きい場合と、どちらも5より大きい場合で計算の仕方が異なるので、多分覚えた方が早い。でも子供にとっては裏技的な方法を知れたというちょっとした喜びが勉強へのハードルを下げてくれるかもなぁと思います。

定期的なイベントを年月日でいい感じに扱うパッケージ almanac

この記事は何?

本記事はRのパッケージ almanac パッケージの紹介です。こちらのGithubに記載してある内容を試した記事になります。 ※一部間違っており修正しました。

davisvaughan.github.io

モチベーション

10月の第2月曜日は何の日でしょう。そう、スポーツの日です。

では、過去10年間のスポーツの日の日付はいつでしたか。と聞かれると一手間かかりますが、そんな一手間を解消してくれそうなパッケージを見つけたので試してみつつ紹介記事を書きます。

 

インストール

remotesパッケージをあらかじめインストールしてください。 vctrsgithubにある物をインストールしてください。

remotes::install_github("DavisVaughan/almanac")

MacWindowsユーザーは問題ないですが、Linuxユーザーの方は上記のページを参照ください。

例:定期的な予定を扱う

例として、thanksgivingが挙げられています。ここでは、11月の第4金曜日というルールのオブジェクトを作っています。

# Thanksgiving = "The fourth Thursday in November"
on_thanksgiving <- yearly() %>%
  recur_on_ymonth("November") %>%
  recur_on_wday("Thursday", nth = 4)

on_thanksgiving
> <rrule[yearly / 1970-01-01 / 2040-01-01]>
> - ymonth: Nov
> - wday: Thu[4]

ルールオブジェクトを生成できたら、これから実際に日付を生成できます。

alma_search("2000-01-01", "2006-12-31", on_thanksgiving)
[1] "2000-11-23" "2001-11-22" "2002-11-28" "2003-11-27" "2004-11-25" "2005-11-24" "2006-11-23"

また、日付に対してルールに該当するかの判定もすることができます。

# Is this a Thanksgiving?
alma_in(c("2000-01-01", "2000-11-23"), on_thanksgiving)
#> [1] FALSE  TRUE

ルールに該当する日を飛ばした日付計算をすることもできます。 2000年は11月23日がthanksgivingでしたが、 11月22日と23日で23日を飛ばした場合の2日後は同じになるという雰囲気です。

step_over_thanksgiving <- stepper(on_thanksgiving)
base_date <- as.Date("2000-11-22")
base_date %s+% step_over_thanksgiving(2)
"2000-11-25"

base_date <- as.Date("2000-11-23")
base_date %s+% step_over_thanksgiving(2)
"2000-11-25"

発展

複数のルールをまとめて扱うこともできる。その場合は、個別のルールーをバンドルしたオブジェクトを作って扱う必要がある。

# 毎週末のルール
on_weekends <- weekly() %>%
  recur_on_weekends()

# クリスマスのルール
on_christmas <- yearly() %>%
  recur_on_mday(25) %>%
  recur_on_ymonth("Dec")

# thanksgivingと週末とクリスマスのルールをまとめたルールを作る
bundle <- rbundle() %>%
  add_rschedule(on_weekends) %>%
  add_rschedule(on_christmas) %>%
  add_rschedule(on_thanksgiving)

日本の出勤日のルールを作ってみる

手を抜いて祝日を除く出勤日ではない日をまとめると、

  • 週末
  • 年末年始(12/28-1/3)
#-----------------------------
on_yearends <- rbundle() %>% 
  add_rschedule(
    yearly() %>% 
      recur_on_ymonth("Dec") %>% 
      recur_on_mday(28)
  ) %>% 
  add_rschedule(
    yearly() %>% 
      recur_on_ymonth("Dec") %>% 
      recur_on_mday(29)
  ) %>% 
  add_rschedule(
    yearly() %>% 
      recur_on_ymonth("Dec") %>% 
      recur_on_mday(30)
  ) %>% 
  add_rschedule(
    yearly() %>% 
      recur_on_ymonth("Dec") %>% 
      recur_on_mday(31)
  )

#-----------------------------
on_yearstarts <- rbundle() %>% 
  add_rschedule(
    yearly() %>% 
      recur_on_ymonth("Jan") %>% 
      recur_on_mday(1)
  ) %>% 
  add_rschedule(
    yearly() %>% 
      recur_on_ymonth("Jan") %>% 
      recur_on_mday(2)
  ) %>% 
  add_rschedule(
    yearly() %>% 
      recur_on_ymonth("Jan") %>% 
      recur_on_mday(3)
  )

#---------------------------
on_japanese_weekday <- rbundle() %>% 
  add_rschedule(on_yearends) %>% 
  add_rschedule(on_yearstarts)

library(stringr)
date_list <- seq(as.Date('2020-01-01'), as.Date('2020-12-31'), 1)

!alma_in(date_list, on_japanese_weekday)

※上記のコードが"Feb"になっていたのを"Jan"に修正しました。

  [1] FALSE FALSE FALSE  TRUE  TRUE  TRUE  TRUE  TRUE  TRUE  TRUE  TRUE  TRUE  TRUE  TRUE  TRUE  TRUE  TRUE
 [18]  TRUE  TRUE  TRUE  TRUE  TRUE  TRUE  TRUE  TRUE  TRUE  TRUE  TRUE  TRUE  TRUE  TRUE  TRUE  TRUE  TRUE
 [35]  TRUE  TRUE  TRUE  TRUE  TRUE  TRUE  TRUE  TRUE  TRUE  TRUE  TRUE  TRUE  TRUE  TRUE  TRUE  TRUE  TRUE
 [52]  TRUE  TRUE  TRUE  TRUE  TRUE  TRUE  TRUE  TRUE  TRUE  TRUE  TRUE  TRUE  TRUE  TRUE  TRUE  TRUE  TRUE
 [69]  TRUE  TRUE  TRUE  TRUE  TRUE  TRUE  TRUE  TRUE  TRUE  TRUE  TRUE  TRUE  TRUE  TRUE  TRUE  TRUE  TRUE
 [86]  TRUE  TRUE  TRUE  TRUE  TRUE  TRUE  TRUE  TRUE  TRUE  TRUE  TRUE  TRUE  TRUE  TRUE  TRUE  TRUE  TRUE
[103]  TRUE  TRUE  TRUE  TRUE  TRUE  TRUE  TRUE  TRUE  TRUE  TRUE  TRUE  TRUE  TRUE  TRUE  TRUE  TRUE  TRUE
[120]  TRUE  TRUE  TRUE  TRUE  TRUE  TRUE  TRUE  TRUE  TRUE  TRUE  TRUE  TRUE  TRUE  TRUE  TRUE  TRUE  TRUE
[137]  TRUE  TRUE  TRUE  TRUE  TRUE  TRUE  TRUE  TRUE  TRUE  TRUE  TRUE  TRUE  TRUE  TRUE  TRUE  TRUE  TRUE
[154]  TRUE  TRUE  TRUE  TRUE  TRUE  TRUE  TRUE  TRUE  TRUE  TRUE  TRUE  TRUE  TRUE  TRUE  TRUE  TRUE  TRUE
[171]  TRUE  TRUE  TRUE  TRUE  TRUE  TRUE  TRUE  TRUE  TRUE  TRUE  TRUE  TRUE  TRUE  TRUE  TRUE  TRUE  TRUE
[188]  TRUE  TRUE  TRUE  TRUE  TRUE  TRUE  TRUE  TRUE  TRUE  TRUE  TRUE  TRUE  TRUE  TRUE  TRUE  TRUE  TRUE
[205]  TRUE  TRUE  TRUE  TRUE  TRUE  TRUE  TRUE  TRUE  TRUE  TRUE  TRUE  TRUE  TRUE  TRUE  TRUE  TRUE  TRUE
[222]  TRUE  TRUE  TRUE  TRUE  TRUE  TRUE  TRUE  TRUE  TRUE  TRUE  TRUE  TRUE  TRUE  TRUE  TRUE  TRUE  TRUE
[239]  TRUE  TRUE  TRUE  TRUE  TRUE  TRUE  TRUE  TRUE  TRUE  TRUE  TRUE  TRUE  TRUE  TRUE  TRUE  TRUE  TRUE
[256]  TRUE  TRUE  TRUE  TRUE  TRUE  TRUE  TRUE  TRUE  TRUE  TRUE  TRUE  TRUE  TRUE  TRUE  TRUE  TRUE  TRUE
[273]  TRUE  TRUE  TRUE  TRUE  TRUE  TRUE  TRUE  TRUE  TRUE  TRUE  TRUE  TRUE  TRUE  TRUE  TRUE  TRUE  TRUE
[290]  TRUE  TRUE  TRUE  TRUE  TRUE  TRUE  TRUE  TRUE  TRUE  TRUE  TRUE  TRUE  TRUE  TRUE  TRUE  TRUE  TRUE
[307]  TRUE  TRUE  TRUE  TRUE  TRUE  TRUE  TRUE  TRUE  TRUE  TRUE  TRUE  TRUE  TRUE  TRUE  TRUE  TRUE  TRUE
[324]  TRUE  TRUE  TRUE  TRUE  TRUE  TRUE  TRUE  TRUE  TRUE  TRUE  TRUE  TRUE  TRUE  TRUE  TRUE  TRUE  TRUE
[341]  TRUE  TRUE  TRUE  TRUE  TRUE  TRUE  TRUE  TRUE  TRUE  TRUE  TRUE  TRUE  TRUE  TRUE  TRUE  TRUE  TRUE
[358]  TRUE  TRUE  TRUE  TRUE  TRUE FALSE FALSE FALSE FALSE

結構便利かも。

以上、さくっと紹介でした。

zshでdplyr-cliを使う

この記事は何

ことをした備忘録です。

 

ことの発端

twitterで流れてきたこれが気になったので使ってみました。

f:id:forest-of-sheep-and-steel:20200423004739p:plain

terminal上でさくっとdplyrを使えるようにしたよ、ということらしいので使ってみます。

 

以下試した内容

githubhttps://github.com/coolbutuseless/dplyr-cli

読んでみると

Only tested under ‘bash’ on OSX. YMMV.

 bashでしかテストしてないということで、zsh環境で動くか試してみました。

githubにも記載されている内容と同様の以下手順です。

 

あらかじめRで下記パッケージをインストール

install.packages('readr')    # read in CSV data
install.packages('dplyr')    # data manipulation
install.packages('docopt')   # CLI description language

 

自身のPCのdplyrのパッケージフォルダにクローン。

パッケージのフォルダが作られる場所はRのコンソールから下記のように確認できます。

> .libPaths()
[1] "/Library/Frameworks/R.framework/Versions/3.6/Resources/library"
 

あとはdplyrのフォルダに移動したら

git clone https://github.com/coolbutuseless/dplyr-cli

 

実際に使う際は、dplyr-cli/dplyrを作業フォルダにコピーします。

cp dplyr-cli/dplyr ./somewhere/in/your/search/path

 

サンプル用にmtcarsのデータセットを作業フォルダに書き出しておきます。

write.csv(mtcars, "mtcars.csv", row.names = FALSE)

 

次のようにzshでも無事実行できました。 

cat mtcars.csv | ./dplyr filter -c "mpg==21"
> "mpg","cyl","disp","hp","drat","wt","qsec","vs","am","gear","carb"
> 21,6,160,110,3.9,2.62,16.46,0,1,4,4
> 21,6,160,110,3.9,2.875,17.02,0,1,4,4

aliasの設定

よく使うやつは下記のようにaliasを貼っておくと便利。

alias mutate="dplyr mutate" alias filter="dplyr filter" alias select="dplyr select" alias summarise="dplyr summarise" alias group_by="dplyr group_by" alias ungroup="dplyr ungroup" alias count="dplyr count" alias arrange="dplyr arrange" alias kable="dplyr kable"

 

もう少しdplyrっぽく

summariseやjoinも使えるようになっています。

cat mtcars.csv | group_by cyl | summarise "mpg = mean(mpg)" | kable
> | cyl| mpg|
> |---:|--------:|
> | 4| 26.66364|
> | 6| 19.74286|
> | 8| 15.10000|

 

サンプルのためあらかじめ次のようなcsvを作っておきます。

#  cyl,description
#  4,four
#  6,six

joinの実行

cat mtcars.csv | ./dplyr inner_join cyl.csv | filter "wt < 3" | select -c mpg, wt, disp, cyl, description | kable

>| mpg| wt| disp| cyl|description |
>|----:|-----:|-----:|---:|:-----------|
>| 21.0| 2.620| 160.0| 6|six |
>| 21.0| 2.875| 160.0| 6|six |
>| 22.8| 2.320| 108.0| 4|four |
>| 32.4| 2.200| 78.7| 4|four |
>| 30.4| 1.615| 75.7| 4|four |
>| 33.9| 1.835| 71.1| 4|four |
>| 21.5| 2.465| 120.1| 4|four |
>| 27.3| 1.935| 79.0| 4|four |
>| 26.0| 2.140| 120.3| 4|four |
>| 30.4| 1.513| 95.1| 4|four |
>| 19.7| 2.770| 145.0| 6|six |
>| 21.4| 2.780| 121.0| 4|four |

 

以上です。

 

今回は、zshでもdplyr-cliが問題なく実行できることを検証できました。

Rを開くほどじゃないけど、dplyr-likeにデータを確認したい、みたいな時に便利そうですね。

 

R Pubs でplotに関するあれこれをまとめました

plotって結構難しい

最近Rを教える機会が何回かあり,Rの強みでもある可視化の基礎,plot関数でつまづく人が多いなぁと感じていました.ウェブ上にほとんどの問題に対する解決策や,目的についての方針を得ることはできるのですが,例とコードと実際の画像がうまくまとまっているものがないなあと思い,描いてみました. まだまだ足りない部分はありますが,今後加筆修正できていければと思います.

rpubs.com

AtCoder ABC114 参加メモ

最近AtCoderに参加し始めました!まだまだ弱いので目も当てられないRatingが続いていますが,備忘録的に書きます. AtCoder始めるまで,統計でRやPython,気が向いてc++やJSにちょっと触ったことあるぐらいでしたので,競プロ耐性はほぼゼロです.
AtCoderには,Rの次に慣れているPythonで参加しています. 過去問解いたり,蟻本読んだりして少しずつ勉強進めていますが,現状C問題が解けるか解けないかという間をさまよっています.

A問題

わかる.

B問題

珍しく簡単

s = input()
res = abs(753 - int(s[0:3]))

for i in range(1,len(s)-2):
    if res > abs(753 - int(s[i:i+3])):
        res = abs(753 - int(s[i:i+3]))

print(res)

C問題

時間内に解けませんでした.単純にfor文回したらだめで,どういう方針で解くか悩んでいるうちに時間切れ.終わってから解説読み,一晩寝かして考えたら解けました.

  1. とりあえず可能性のある数字を全部列挙する
    • 列挙するにあたり,まずは7,5,3のいずれかで構成される数字を列挙する.(7だけとか3だけもOK)
  2. 列挙したものの中から,条件を満たす要素数を数える
#----------------
# 入力パート
s = input()
#----------------

#----------------
# 列挙パート
all_list = []

# 3桁未満はありえないので3桁の数を列挙
for i in '753':
    for j in '753':
        for k in '753':
            all_list.append(''.join([i,j,k]))

# 与えられた数字の桁数まで,既に列挙してあるものの先頭に7,5,3を付け足していく
for i in range(4,len(s)+1):
    add_list = []
    for c in '753':
        add_list += [''.join(c+e) for e in all_list]
    all_list += add_list

# 重複を排除する
all_list = set(all_list)
#----------------

#----------------
# 回答パート 
# 各要素を集合に変換して{'7','5','3'}と同じになり,かつ与えられた数以下であるかを判定し合計する
res = sum([True for _ in all_list if set(list(_))=={'7','5','3'} and int(_) <= int(s)])
print(res)
#----------------

競技プログラミングにもっと早く出会いたかった.

Rでcaretがインストールできない人へ

caretを使おうと思ったらそもそもインストールエラーで丸一日潰した話

caret便利そうなので一通り触ってみるかと思ってインストールしたらエラーorz

fatal error: not found omp.h

色々調べまくってOpenMPをちゃんと呼び出せてないらしいということまでが分かったが 解決できず丸一日を費やしてしまってもうRは終わったんやとおもってた。

次の日気を取り直してまた調べてたら、以下の記事を見て、

qiita.com

まさかそもそもhomebrewからRをインストールしたせいか・・・、と疑い 一旦homebrewからRを抹消して直でCRANからインストールしてみたら・・・、

普通に動いた

しばらくはhomebrew経由でRをインストールするのはやめようと思いました。

検証はしていないのですが、 Rで not found omp.h というエラーが出ていてhomebrew経由で インストールしているからは一旦やめてみるのが良いかもしれません。

prettydocパッケージを使ってみた

Rstudio、Rmarkdownで資料作成するとき、いい感じのテンプレート提供してくれるパッケージを使って見ました。

 

>|r|
install.packages("prettydoc")
||<

これを走らせておいて、

Rstudioで file ->  New file -> R markdown -> From Template からPretty Document が2種類追加されている。どちらかを選んで作成するだけ。

 

そんなに堅苦しくない報告書やレポートを作るのに便利かも!

開発者のデモページはこちら

Creating Pretty Documents from R Markdown