Vectorにmax()やmin()をかませたかった [R]

Rの話です。

Problem

同じ次元の2つのvectorを適当に用意します。

> n <- round(rnorm(8)) # 正規分布
> n
[1]  1 -1  0  1  2  1 -1  1
> u <- round(runif(8), 3) # 一様分布
> u
[1] 0.292 0.774 0.411 0.009 0.634 0.378 0.985 0.468

これら2つのvectorの各成分を比較して、大きい方の値をとるような3つ目のvectorを作りたくなりました。
つまり、各  i = 1, 2, ..., 8に対し  m_i = \max ( n_i, u_i) となるようなvector  mを作りたくなりました。

> max(n, u)
[1] 2

うまくいきませんでした。1

Solution

調べたら、pmax()とかいうのを使えばうまくいくことがわかりました。

> pmax(n, u)
[1] 1.000 0.774 0.411 1.000 2.000 1.000 0.985 1.000

このpmax()を使えば、vectorに対し正部分をとるような操作、すなわち、各成分の値が0以上ならその値を、0未満なら0をとるような操作も施せました。

> n
[1]  1 -1  0  1  2  1 -1  1
> pmax(n, 0)
[1] 1 0 0 1 2 1 0 1
> max(n, 0)
[1] 2

もちろんmin()やpmin()についても同様のことが言えます。


  1. 前回の記事よろしく、実際は8次元ではなく数百万〜数千万次元のvectorを扱っていたので、for文は避けたい、という気持ちがありました。

エスペラント検定を受験した [Esperanto]

試験当日のことをまず述べ、続いて試験前日まで何をしたのかについて軽く触れ、最後に今後のことについて記す。

試験当日のこと

f:id:q19:20210327182435j:plain
エスペラント会館
試験会場はエスペラント会館。
東西線早稲田駅の1番出口から出て徒歩1分。
エスペラント会館、と書かれた大きな垂れ幕がビルにかかっていたので、分かりやすかった。

初めてエスペラント会館に入館した。
1Fに案内板があり、3Fが事務所と書いてあったので、3Fに向かった。
階段を登る途中、踊り場で女性とすれ違い、挨拶された。

“Saluton!”

咄嗟にesperantoが出てこず、こんにちは、と返してしまった。

f:id:q19:20210327182549j:plain
3F事務所
3Fに行くと、staffらしき男性がいたので、検定を受けに来た旨を伝えると、試験会場は4Fだと教えてくれた。
4Fに行くと、試験会場があった。
名前を告げると受験番号を告げられた。
座席表の通りに着席し受験票を記入した。

その日に集まった受験生は8名ほどで、1級から4級まで全員同じ部屋で同時に筆記試験を受けた。
全員集まったところで、以下の内容を含む簡単な説明があった:

  • (今回私が受験する)4級の試験時間は60分
  • 早く解き終わった場合は早期退出が可能
  • 早期退出のあと、(その瞬間に会話試験を受験している人がいない場合)すぐに会話試験を受験可能
  • 試験結果は1ヶ月以内に葉書で知らされる

筆記試験。
いくつか見たことがない単語があり、分からない部分は素直に空欄にした。
HPに載っていた例題よりも若干難しいと感じた。
体感、7割は取れたかな、という感触。
筆記試験は60分だったが10分程度で解き終わったので早期退出し、会話試験を受けに別室に向かった。1

会話試験は私と試験官1名の対面で行われた。2
詳細な試験内容をここで詳らかにするのは控えるが、エスペラント協会のHPに載っている例題と似ていた。
前半は渡された問題用紙を読み上げるのがほとんどで、後半は試験官からの質問に簡単なesperantoで答える形式だった。
試験官の説明は丁寧で、esperantoの発音も明瞭なのがありがたかった。

試験終了後、3Fの売店問題集を見つけたので、おみやげに購入。

Staffらしき方々や試験運営の方々は皆親切で、とても気持ちがいいと思った。

試験前日までのこと

3ヶ月くらい前からDuolingoesperantoを学び始めた。
一日に何分学習するか、目標を予め入力し、その目標を何日連続で達成できたかが表示されるので、motivationが維持される。
このDuolingoによる学習を毎日10分程度、3ヶ月に亙り行い、試験直前に例題を暗記して試験に臨んだ。
試験当日は語彙力と会話経験の不足を感じた。
自己紹介をesperantoでできるくらいにはしたほうが安心だと思った。

今後のこと

Duolingoによる学習は楽しいので継続するつもり。
ほかの資格試験との兼ね合いで、余力があれば上の級も受けたいけど、今回の結果が不合格だったらやる気無くなっちゃうかも。


  1. とあるblogで4級受験者が余った時間で3級を受けさせてもらえた例を見たが、試験終了後に3級受験の提案はなかった。

  2. 受験の様子をほかの受験者に聞かれることはなさそう。

Matrixの特定の要素を取り出しvectorに並べる [R]

Rの話です。

Problem

Matrixから特定の要素を抜き出してvectorを作ろうとしたところ、なぜかmatrixが生成されて困ってしまいました。
たとえば、次のようなmatrixを考えます。

> mat <- matrix(1:100, 10, 10)
> mat
      [,1] [,2] [,3] [,4] [,5] [,6] [,7] [,8] [,9] [,10]
 [1,]    1   11   21   31   41   51   61   71   81    91
 [2,]    2   12   22   32   42   52   62   72   82    92
 [3,]    3   13   23   33   43   53   63   73   83    93
 [4,]    4   14   24   34   44   54   64   74   84    94
 [5,]    5   15   25   35   45   55   65   75   85    95
 [6,]    6   16   26   36   46   56   66   76   86    96
 [7,]    7   17   27   37   47   57   67   77   87    97
 [8,]    8   18   28   38   48   58   68   78   88    98
 [9,]    9   19   29   39   49   59   69   79   89    99
[10,]   10   20   30   40   50   60   70   80   90   100

このmatの(1, 4), (2, 5), (3, 6)成分を取り出してvectorを作ろうと考えたのですが、vectorではなくmatrixが得られてしまいました。

> r <- c(1, 2, 3)
> c <- c(4, 5, 6)
> mat[r, c]
     [,1] [,2] [,3]
[1,]   31   41   51
[2,]   32   42   52
[3,]   33   43   53

Solution

調べると、cbind()という人がいい感じにやってくれることがわかりました。

> mat[cbind(r, c)]
[1] 31 42 53

すぐ思いつくような方法として、for文で地道に生成する方法

> dim <- length(r)
> vec <- numeric(dim)
> for(k in 1:dim)
+   vec[k] <- mat[r[k], c[k]]
> vec
[1] 31 42 53

や、diag()によりmatrixの対角成分だけ取り出す方法

> diag(mat[r, c])
[1] 31 42 53

がありますが、数万〜数千万次元の巨大なvectorを作りたかったので、計算時間の観点からfor文は避けたいという気持ちがありました。
実際、計算時間を計測してみると、cbind()の方法は0.035秒、for文の方法は1.6秒かかり、diag()の方法に至っては、実行するとRがフリーズしてしまい、最後まで計算を行えませんでした。

> r <- round(runif(10^6, min = 1, max = 10)) # 適当に10^6コ自然数生成
> c <- round(runif(10^6, min = 1, max = 10)) # 上に同じ
> dim <- length(r) # 10^6
> vec <- numeric(dim)

> start <- Sys.time()
> vec <- mat[cbind(r, c)]
> end <- Sys.time()
> end - start
Time difference of 0.03506589 secs

> start <- Sys.time()
> for(k in 1:dim)
+   vec[k] <- mat[r[k], c[k]]
> end <- Sys.time()
> end - start
Time difference of 1.6093 secs

> start <- Sys.time()
> vec <- diag(mat[r, c]) # ここでRがフリーズする

フリーズの原因は巨大な行列を生成したことっぽいですが、あんまり興味がわかないのでこの辺で。

Blog 開設

Twitterに投下するには文字数が多すぎる内容や、備忘録的な内容を投下するために、はてなブログのaccountを取得した。
記事を書くにあたって、編集方法の選択を要求された:

ググるMarkdownのほうが汎用性が高いそうなので、頑張ってMarkdownの記法に慣れようと思う。