R苦手の会#5(Skype読書会)

id:wakuteka主催の読書会も5回目です.今回もid:syou6162が参加してたくさんの脱線興味深いお話を聞かせてくれました.

のーと

範囲:http://www1.doshisha.ac.jp/~mjin/R/04.html
本だと最初の方にfunctionあったり先日の基本統計量のところにapplyあったり断片的に散らばってるぽい.

準備

7つのグループに4つの選択肢のアンケートをした結果.

> ## 7つのグループ,4つの選択肢
> life1<-matrix(0,7,4)
> life1[,1]<-c(101,153,89,26,36,167,125)
> life1[,2]<-c(120,162,135,49,70,216,143)
> life1[,3]<-c(70,88,78,42,30,144,89)
> life1[,4]<-c(35,46,24,17,16,71,65)
> 
> colnames(life1) <- c("A1", "A2", "A3", "A4")
> rownames(life1) <- LETTERS[1:7]
> life1
   A1  A2  A3 A4
A 101 120  70 35
B 153 162  88 46
C  89 135  78 24
D  26  49  42 17
E  36  70  30 16
F 167 216 144 71
G 125 143  89 65
applyを使ってみよう!

applyを使うと行や列ごとに関数を使える.

> ## Applyでグループごとの和を求める
> apply(life1, 1, sum)                    # 行に
  A   B   C   D   E   F   G 
326 449 326 134 152 598 422 
> apply(life1, 2, sum)                    # 列に
 A1  A2  A3  A4 
697 895 541 274 
> apply(life1, 1:2, log)                  # 各項目
        A1       A2       A3       A4
A 4.615121 4.787492 4.248495 3.555348
B 5.030438 5.087596 4.477337 3.828641
C 4.488636 4.905275 4.356709 3.178054
D 3.258097 3.891820 3.737670 2.833213
E 3.583519 4.248495 3.401197 2.772589
F 5.117994 5.375278 4.969813 4.262680
G 4.828314 4.962845 4.488636 4.174387

第一引数はデータフレームや行列を与える.
第二引数が1なら行に,2なら列に関数を使う.
第三引数に使う関数を指定.
これをforで書き直すと

> ## for
> ans <- numeric(0)
> for(i in 1:7){
+   ans[i] <- sum(life1[i,])
+ }
> ans
[1] 326 449 326 134 152 598 422

というような感じなので,第二引数は行列に与える添え字の位置と対応させて数字にしてるのかななどと思った.中身みたら長かったので読んでないけど…
あわせてよみたい:apply familyの紹介 - yasuhisa's blog
単語とその登場回数だけが記録されたデータフレームから元のベクトルを復元とかそういう使い方もするらしい.

> ## 単語,登場回数の一覧から元のベクトルを復元
> word <- c("a", "b", "c")
> count <- c(3, 4, 1)
> d <- data.frame(word, count)
> 
> ## 各行で複数の要素が帰ってくる場合リストになる
> ## そのためunlistでベクトルに戻している
> unlist(apply(d, 1, function(x){rep(x[1],x[2])}),
+        use.names=FALSE)
[1] "a" "a" "a" "b" "b" "b" "b" "c"

ここでは無名関数を使っている.こんな感じでその場でちょいちょいと関数を定義して代入せずに使える.

roundさんはroundされましたけど

後のためにデータだけ作成.まあroundくらい分かりますよね*1

> ## グループごとの和で割って割合を出す
> (life2 <- round((life1/apply(life1, 1, sum))*100, 2))
     A1    A2    A3    A4
A 30.98 36.81 21.47 10.74
B 34.08 36.08 19.60 10.24
C 27.30 41.41 23.93  7.36
D 19.40 36.57 31.34 12.69
E 23.68 46.05 19.74 10.53
F 27.93 36.12 24.08 11.87
G 29.62 33.89 21.09 15.40
関数はfunction関数を使用して(ry

グループごとの平均値と各データの差を計算して表示する関数を作成.

> ## さあ関数を作るぞ!!
> hensa <-  function(x){
+   round(t(t(x) - apply(x, 2, mean)), 2)
+ }
> hensa(life2)
--
> ## apply使おうぜ!! by 6162
> hensa2 <- function(x){
+   apply(x, 2, function(y){round(scale(y,scale=F),2)})
+ }
> hensa2(life2)
--
> ## 引数には省略時の規定値を設定できる
> hensa3 <-  function(x=life2){
+   hensa(x)
+ }
> hensa3()
--

ちなみに引数と省略時規定値のリストはhelp以外にformals()関数で取得できる.

if for
> ## if
> if(life2[1, 1] > mean(life2[ ,1])){
+   print("TRUE")
+ }else{
+   print("FALSE")
+ }
[1] "TRUE"
> 
> ## for
> for (i in 1:7){
+   if(life2[i,1]>mean(life2[,1])){
+     print("TRUE")
+   }else{
+     print("FALSE")
+   }
+ }
--
> for(j in 1:4){
+   for (i in 1:7){
+     if(life2[i,j]>mean(life2[,j])){
+       print("TRUE")
+     }else{
+       print("FALSE")
+     }
+   }
+ }
--

おまけ

平均より大きいのに○,小さいのに×つけてみ by 6162
apply(life2,2,
function(x){symnum(x,
cutpoints=c(0,mean(x),100),
symbols=c("×","○")
)})

ふふん*2

*1:あとExcelだと四捨五入だけどroundはちゃんとJIS丸めしてるとかそんなのも知ってますよねもちろん.

*2:最初applyの第二引数間違えてた.そのときの名残で転置しててやぐさんから素早い突っ込みを食らった.

Word2007の数式ビルダを使って数式を作成しよう

Officeを買ったのでWordで数式を入力する方法を少しまじめに調べた.
試用版をなんとなく使っていた時は知らなかったけど,Word2007からは今までのあの使いにくくてカッコ悪い数式エディタ*1ではなくて,数式ビルダというものが数式入力のための規定のツールになっている.

数式ビルダはこんなに便利!

数式ビルダはおそらくかなりTeXを意識して作られている.というのも,ほぼTeXのコマンドをそのまま入力するだけで数式の入力が完了するからだ.
たとえば,数式の入力エリアに次のようにコマンドを入力する.ちなみに[C-i]はCtrl+iです*2

[C-i]\sum_(i=1)^\infty x^i = 1/(1-x)

そうすると,こんな具合に出力してくれる.

このとき入力する\sumだとかいうコマンドは,適当なタイミングでスペースキーを叩くだけで組み立てられる.つまり,TeXっぽい簡単な数式入力ができる上に,数式の形を確認しながらの入力もできる.これは数式入力だけならばTeXよりも使いやすいと思う.
数式のエリアは[Alt]→N→E→Iと順番にタイプするだけで挿入できる.もしその行に数式がそれしかなければ上記の例のような別行立ての形になり,前後に文字が存在していれば文中のスタイルにしてくれる.また,そのほかに行形式と呼ばれる数式を行の形(Σ_(i=1)^∞=1/(1-x)のように)にするスタイルもある.
さらに,よく使う数式は登録しておくこともできるのだ!
さあこれでもうTeXからWordに乗り換えてもあんしん………とはいかない.さすが期待を裏切らない.

数式ビルダはこんなに不便!!

数式ビルダで作成される数式の外観はこれまでの数式エディタに比べるとずいぶんまともだ.積分とかも綺麗に見える.これはCambria Mathという数式組版のために開発されたフォントのおかげで達成されている.だが残念なことに数式ビルダの規定のフォントはCambria Mathしか選べない*3
また,新しく追加された機能だから仕方ないといえば仕方ないのだが古いバージョンのWordとの互換性がない.また,PowerPointなどにコピペしても小さなサイズの画像になってしまってイマイチ使えない.このあたりをどうしてもどうにかしたかったら昔の数式エディタを使うしかない*4
さらに信じられないことなのだが,せっかく数式を入力しても数式番号をつける手段がデフォルトでは用意されていない.かなり探したけどどうやら本当に用意されていないらしい.[参考資料]タブの[図表番号の挿入]や[相互参照]にはラベルや項目に[数式]が用意されているのに連携していないのだ.

ないものは作りましょう

幸いなことに数式入力エリアを自作して登録しておくことができる.
適当にそれっぽいものを作成して範囲選択して[挿入]タブの[数式]から[選択範囲を数式ギャラリーに追加]するだけ.
どうもWord2007ユーザーの間ではテーブルを駆使して数式エリアを作成するというのが一応の解答になっているようだ*5
必要に応じて適当に作って登録すればいいのだが,一応次のようにやるとそれっぽくて番号の参照にも便利なやつが作成できる.

  1. 1行3列の表を作成
  2. 表を選択し,[レイアウト]タブの[プロパティ]を開く
  3. [幅を指定する]にチェックし,基準をパーセント,値に100%を指定する
  4. [列]タブで列の幅をパーセントで指定,10%,80%,10%など左右を狭く同じ値にする
  5. [レイアウト]タブに戻り[配置]で中央のセルを中央揃え,右のセルを右揃え(中央)に
  6. 表全体を選択し,[デザイン]タブの罫線から罫線なしを選択し罫線を消す
  7. 中央のセルにカーソルを移動させ,[Alt], N, E, Iとタイプして数式エリアを作成(入力はしない)
  8. 適当な場所で[参考資料]タブから[図表番号の挿入]を選択
  9. ラベルに[数式]を選択し,[ラベルを図表番号から除外する]にチェックを入れてOKをクリックすると番号が出てくる
  10. 作成した番号を右側のセルにコピーペーストなどで移動させ,必要に応じて前後に括弧などを記入,フォントもボールドになっているので気に入らなければ[ホーム]タブから解除しておく
  11. 作成した表全体を選択,[挿入]タブの[数式]から[選択範囲を数式ギャラリーに追加]し,適当な名前で保存する

こうしておけば,[Alt], N, E, [Enter]とタイプ(ほかに数式を追加してなければ)するだけで数式番号付きの数式エリアが作成される.

数式番号は[参考資料]タブから[相互参照]を選択し,[参照する項目]に数式を選べば利用できる.TeXの\refみたいなもの.

*1:ちなみに使おうと思えば使える

*2:残念なことに数式がデフォルトでイタリックにならないというバグがあるらしく,最初にイタリックにするためのショートカットであるCtrl+Iを入力しないときれいにならない

*3:選べるということは追加の予定があるのだろうか?一応数式作成後に数式を選択してフォントを変更することはできるが,必ずしも反映されないしまず汚くなる.

*4:インストールしてあれば[挿入]タブの[オブジェクト]から数式 3.0を選択して挿入できる

*5:そういえばOOoのWriterも数式と数式番号の配置は表で実現してた