普通のプログラミング言語r

76
普通の プログラミング言語 R() 2010/5/9 id:n_shuyo / @shuyo 中谷 秀洋@サイボウズ・ラボ

Upload: shuyo-nakatani

Post on 01-Nov-2014

13 views

Category:

Technology


5 download

DESCRIPTION

Tsukuba.R #7

TRANSCRIPT

Page 1: 普通のプログラミング言語R

普通のプログラミング言語 R(仮)

2010/5/9 id:n_shuyo / @shuyo

中谷 秀洋@サイボウズ・ラボ

Page 2: 普通のプログラミング言語R

最近

Page 3: 普通のプログラミング言語R

機械学習

Page 4: 普通のプログラミング言語R
Page 5: 普通のプログラミング言語R

いろいろ実装してみたくて

Page 6: 普通のプログラミング言語R

R始めました

Page 7: 普通のプログラミング言語R

そんなわけで

Page 8: 普通のプログラミング言語R

R歴

Page 9: 普通のプログラミング言語R

まもなく1年

Page 10: 普通のプログラミング言語R

Rって便利ですね!

Page 11: 普通のプログラミング言語R

K-means クラスタリングの更新式

これがE-step:

rnk = 1 (k = argminj 𝐱n − 𝛍j

2のとき)

0 (それ以外)

M-step:

𝛍k = rnk 𝐱nn

rnkn

Page 12: 普通のプログラミング言語R

Rなら1行

mu<-t(sapply(1:K,function(k)colMeans(x[max.col(-sapply(1:K,function(i)colSums((t(x)-mu[i,])^2)))==k,])));

Page 13: 普通のプログラミング言語R

Rってほんと便利!!

Page 14: 普通のプログラミング言語R

でも……

Page 15: 普通のプログラミング言語R

Rって……

Page 16: 普通のプログラミング言語R

変ですよね?

Page 17: 普通のプログラミング言語R

すごいことが簡単にできるけど

Page 18: 普通のプログラミング言語R

簡単なことがやたら難しかったり

Page 19: 普通のプログラミング言語R

予想と違う動きでハマったり

Page 20: 普通のプログラミング言語R

ぺけBASIC

Excel VBA

MSX-BASIC

Visual BASIC

MC68000

PHP

いままで結構いろんな言語を触ってきたつもりだけれど──

MS-BASICZ80

RErlang

C++C

Ruby

Brainf*ck

X-BASIC

Java

javascriptActionScript

Python

XSLT

PL/SQL

COBOL Perl

6502/680x x86

Page 21: 普通のプログラミング言語R

気持ち悪いと思った言語は

R だけ

Page 22: 普通のプログラミング言語R

Rの一番良いところは統計学者が作っているところだ。

Rの一番悪いところは統計学者が作っているところだ。

[要出典]

Page 23: 普通のプログラミング言語R

[出典]

Page 24: 普通のプログラミング言語R

でも R だって

Page 25: 普通のプログラミング言語R

普通のプログラミング言語になりたいはず!

Page 26: 普通のプログラミング言語R

そのためには

Page 27: 普通のプログラミング言語R

「普通のプログラミング言語」の

「普通のプログラミング」ができるようになれば!

Page 28: 普通のプログラミング言語R

もちろん

Page 29: 普通のプログラミング言語R

メタプログラミングのことですね!

Page 30: 普通のプログラミング言語R

Rで普通のメタプログラミング

2010/5/9 id:n_shuyo

Page 31: 普通のプログラミング言語R

R って意外と

Page 32: 普通のプログラミング言語R

インスペクトと動的定義が

得意なんですよ!

Page 33: 普通のプログラミング言語R

というわけでクイズです

Page 34: 普通のプログラミング言語R

次の文を実行したとき、f は何になるでしょう?

f <- function(x){x*2};

Page 35: 普通のプログラミング言語R

関数?

Page 36: 普通のプログラミング言語R

正解は「クロージャ」

> f <- function(x){x*2}> typeof(f)

[1] "closure"

Page 37: 普通のプログラミング言語R

「クロージャ」って

Page 38: 普通のプログラミング言語R

なんかあの難しいやつ

Page 39: 普通のプログラミング言語R

クロージャ(クロージャー、closure、閉包)はプログラミング言語における関数の一種。引数以外の変数を実行時の環境ではなく、自身が定義された環境(静的スコープ)において解決することを特徴とする。関数とそれを評価する環境のペアであるともいえる。

Wikipedia「クロージャ」

Page 40: 普通のプログラミング言語R

「関数とそれを評価する環境のペア」

Page 41: 普通のプログラミング言語R

たしかにクロージャ

> f <- function(x){ x*2 };> body(f) # 関数本体{

x * 2}> environment(f) # 環境<environment: R_GlobalEnv>

Page 42: 普通のプログラミング言語R

グローバル環境はワークスペースのルートをなす

.GlobalEnv がエイリアス

グローバル環境

> environment(f)<environment: R_GlobalEnv>> .GlobalEnv<environment: R_GlobalEnv>

Page 43: 普通のプログラミング言語R

ls.str(環境) もしくは as.list(環境)で見ることが出来る

環境の中身を見る

> a <- 1> ls.str(.GlobalEnv)a : num 1f : function(x)> as.list(.GlobalEnv)$a[1] 1$ffunction(x){x*2}

Page 44: 普通のプログラミング言語R

関数は子環境を作る> f <- function(x) {+ print(environment());+ print(parent.env(environment()));+ print(as.list(environment()));+ }> f(3)<environment: 0x064bd8f0> # 子環境<environment: R_GlobalEnv> # 親環境$x # 子環境の中身[1] 3 # ←3が出る仕組みは別の長い話

Page 45: 普通のプログラミング言語R

子環境は毎回作られる関数は呼び出されるごとに子環境を作成する(スコープの話はしません)

> f <- function() {+ print(environment());+ }> f()<environment: 0x06dbdd54> # 子環境1> f()<environment: 0x06ca9c28> # 子環境2

Page 46: 普通のプログラミング言語R

クロージャは環境とひもづく

定義されたときの環境を「閉包」

> f <- function() {+ print(environment());+ function() {}+ }> g <- f()<environment: 0x061d5cb4> # f の子環境> environment(g) # ||<environment: 0x061d5cb4> # g の環境

Page 47: 普通のプログラミング言語R

クロージャの環境の中身> f <- function() {+ x <- 3+ function(a){ a * x } # 環境を閉包+ }> g <- f()> gfunction(a){ a * x } # x って何?<environment: 0x06dbe0b8> # この中を見れば…> ls.str(environment(g))x : num 3 # g の環境では x <- 3> g(2)[1] 6 # つまり g は値を3倍する関数

Page 48: 普通のプログラミング言語R

準備完了

Page 49: 普通のプログラミング言語R

クロージャをいじってみよう!

Page 50: 普通のプログラミング言語R

クロージャの環境は外からいじれる

> as.list(environment(g))$x[1] 3> environment(g)$x <- 4 # 書き換え!> ls.str(environment(g))x : num 4> g(2)[1] 8 # 値を4倍する関数に変わった!

Page 51: 普通のプログラミング言語R

環境のまるごと差し替えnew.env() で新しい環境を作成し、クロージャの環境に差し替える

> e <- new.env() # 環境の作成> e$x <- 5 # 値をセット> environment(g) <- e # 差し替え> ls.str(environment(g)) # 環境を確認x : num 5> g(3)[1] 15 # 値を5倍する関数に!

Page 52: 普通のプログラミング言語R

関数本体も差し替え!> gfunction(a){ a * x } # 掛け算する関数<environment: 0x06dbe0b8>> body(g) <- expression({ a + x })> gfunction (a) {

a + x # 足し算する関数になった!}<environment: 0x06dbe0b8>> g(1)[1] 6 # 5を足す関数に変わった

Page 53: 普通のプログラミング言語R

引数だっていじれる!

> formals(g)$a # 引数 a を持つ。デフォルト値なし

> formals(g)$a <- 2> formals(g)$a[1] 2 # 引数 a のデフォルト値が 2 に

> g()[1] 7 # 2 + 5

Page 54: 普通のプログラミング言語R

結論

Page 55: 普通のプログラミング言語R

Rかわいいよ!

Page 56: 普通のプログラミング言語R

え?

Page 57: 普通のプログラミング言語R

「それがなんの役に立つの?」

Page 58: 普通のプログラミング言語R

……

Page 59: 普通のプログラミング言語R

……えーと、

Page 60: 普通のプログラミング言語R

こんな感じで「R の中身」がわかってくると

Page 61: 普通のプログラミング言語R

R で「できること」と「できないこと」が

Page 62: 普通のプログラミング言語R

わかるようになるかもね!(棒読み)

Page 63: 普通のプログラミング言語R

ま、

Page 64: 普通のプログラミング言語R

役に立つかなんて

Page 65: 普通のプログラミング言語R

一番つまんない尺度ですよね!

Page 66: 普通のプログラミング言語R

[没ネタ集]

Page 67: 普通のプログラミング言語R

「Rで変なコードを書こう!」とか

遅延評価ってわかりにくいよね。

> a[1] 0> g <- f(a<-3) # f は「とある関数」> a[1] 0 # a は 0 のまま> g() # でも g() を呼ぶと……> a[1] 3 # 3 に変わる

Page 68: 普通のプログラミング言語R

「なんでエラーなの?」とかなぜか plot できない!

しかもエラーメッセージが意味不明

(わかる人にはわかるけど、わかる人はこんなコード書かない)

> plot(function(x) x+x^2); # 問題なし> f <- function(x) c(x,x^2);> plot(function(x) sum(f(x)))以下にエラー xy.coords(x, y, xlabel, ylabel, log) :

'x' and 'y' lengths differ # 何このエラー?

Page 69: 普通のプログラミング言語R

「なんでエラーじゃないの?」とか

「なんでそんな書き方出来るの?文法どうなってんの?」って思うことありません?

> f(abc) # f は「よくある関数」以下にエラー f(abc) :オブジェクト 'abc' がありません

> g(abc) # g は「とある関数」> # あれ? エラーにならない……

Page 70: 普通のプログラミング言語R

「あるある~」小ネタとかplot() の重ね描きで、同じ引数を何度も書かなくて済む方法ないの?

plot(data1,xlim=c(-5,5), ylim=c(-5,5), ann=F);

par(new=T);plot(data2,

xlim=c(-5,5), ylim=c(-5,5), ann=F);par(new=T);plot(data3,

xlim=c(-5,5), ylim=c(-5,5), ann=F);

Page 71: 普通のプログラミング言語R

などなど

Page 72: 普通のプログラミング言語R

ほかにも

Page 73: 普通のプログラミング言語R

いろいろ

Page 74: 普通のプログラミング言語R

なくもなかったんですけど

Page 75: 普通のプログラミング言語R

時間ないのでまたの機会(あるかな?)

Page 76: 普通のプログラミング言語R

ありがとうございました。