chapter 6: computing on the language (r language definition)

29
R Language Definition version 2.14.2(2012-02-29) DRAFT Chapter 6: Computing on the language Tokyo.Lang.R #2 2012/06/02 @teramonagi

Upload: tera-monagi

Post on 15-Jan-2015

2.839 views

Category:

Technology


1 download

DESCRIPTION

Tokyo.Lang.R #2(http://atnd.org/events/28465)でのトーク資料。

TRANSCRIPT

Page 1: Chapter 6: Computing on the language (R Language Definition)

R Language Definitionversion 2.14.2(2012-02-29) DRAFT

Chapter 6: Computing on the language

Tokyo.Lang.R #22012/06/02

@teramonagi

Page 2: Chapter 6: Computing on the language (R Language Definition)

6 Computing on the language• R は Lisp よりも親しみやすいインターフェイ

ス• しかし、計算エンジンは Lisp- l ike• (数式の)“ expression” にアクセス可能• 微分等を解析的に計算可能!( Not 数値的)• example

> curve(sin(x))> curve(cos(x))

2

Page 3: Chapter 6: Computing on the language (R Language Definition)

6.1 Direct manipulation of language objects

• Language objects は3種類1. call2. expression3. function

• まずは call object についてのお話• call object = “unevaluated expressions”

– quote 関数で生成– その名の通り“まだ評価されていない”– eval 関数で評価してやる– [[]] で list-like に表現の各要素?にアクセス可能

3

Page 4: Chapter 6: Computing on the language (R Language Definition)

6.1 Direct manipulation of language objects

> e1 <- quote(2 + 2)> mode(e1)[1] "call"> typeof(e1)[1] "language"> e1[[1]]`+`> e1[[2]][1] 2> e1[[3]][1] 2

> as.list(e1)[[1]]`+`

[[2]][1] 2

[[3]][1] 2

call 型

List のようにアクセス可能

4

実際これでList になる

Page 5: Chapter 6: Computing on the language (R Language Definition)

6.1 Direct manipulation of language objects

> mode(e1[[1]])[1] "name"> mode(e1[[2]])[1] "numeric"> mode(e1[[3]])[1] "numeric"> e1[[1]] <- as.name("*")> e12 * 2

> e1[[2]] <- e1> e12 * 2 * 2

演算子 (+,* 等 ) や変数は” name”

演算子の挿げ替え(関数も可)

call を要素?として代入する事も可能

5

Page 6: Chapter 6: Computing on the language (R Language Definition)

6.1 Direct manipulation of language objects

> x <- quote(c(1,2))> as.list(x)[[1]]c[[2]][1] 1[[3]][1] 2> deparse(x)[1] "c(1, 2)"> class(deparse(x))[1] "character"

> deparse(quote("-"(2,2)))[1] "2 - 2"> deparse(quote(2 - 2))[1] "2 - 2"

同じ表現に deparseされるとは限らない

deparse(call→ 文字列化)

6

Page 7: Chapter 6: Computing on the language (R Language Definition)

6.2 Substitutions• “expression” を plot ラベルとして文字列化したい• そんな時の substitute 関数。俗に言

う“ deparse” (オブジェクト⇒文字)• 遅延評価に使われる” promise” オブジェクトの

expression スロットの値を引っこ抜く• “promise” オブジェクトは

– expression :中身の“表現”– environment :評価される際の“環境“– value :(もし一度評価されているなら)その“値“

の3つの SLOT を持っている( 2.1.8 より)7

Page 8: Chapter 6: Computing on the language (R Language Definition)

0.6 0.8 1.0 1.2 1.4

-1.0

0.0

1.0

Index

0

x10.8413447x2 0.9772499x3 0.9986501x4 0.9999683

6.2 Substitutionsplot(0)for(i in 1:4){ text(1, 0.2 * i, substitute(x[ix] == y, list(ix = i, y = pnorm(i))))}

8

Page 9: Chapter 6: Computing on the language (R Language Definition)

0.6 0.8 1.0 1.2 1.4

-1.0

0.0

1.0

Index

0

x1 0.8413447x2 0.9772499x3 0.9986501x4 0.9999683

6.2 Substitutionsplot(0)for( i in 1:4){ text(1, 0.2 * i, bquote(x[.(i)] == .(pnorm(i)) ))}

9

bquote 関数で略記が可能

Page 10: Chapter 6: Computing on the language (R Language Definition)

6.2 Substitutions> expr <- quote(x + y)> not.nested <-

substitute(expr, list(x = 3))> class(not.nested)[1] "name"> typeof(not.nested)[1] "symbol"> eval(not.nested)x + y

> nested <- substitute(substitute(e, list(x = 3)), list(e = expr))

> class(nested)[1] "call"> typeof(nested)[1] "language"> eval(nested)3 + y

substitute をネストして適用

第一引数( quote(x+y)) を評価しないので正しく deparse (文字列化されない) 10

Page 11: Chapter 6: Computing on the language (R Language Definition)

6.2 Substitutions> default <- 1> f <- eval(bquote( function(x, y = .(default)) x+y ))> f(2)[1] 3

11

かなりヤンチャな書き方もできる。。。が、可読性が。。。

Page 12: Chapter 6: Computing on the language (R Language Definition)

6.2 Substitutions• 厳密なルール

– パースツリーのそれぞれのシンボルが第二引数(タグ付されたリストか環境)にマッチされる

– シンボルがローカル変数の場合は、そのローカルの値が挿入される(グローバル環境にマッチされる場合除く)

– シンボルが promise (関数の引数等)ならその表現が代入される(たぶん遅延評価の事)

– substitute の前にローカル変数が変更された場合、R は新しい値を使う一方、 S の場合は argument expression を使う

12

Page 13: Chapter 6: Computing on the language (R Language Definition)

5 10 15

0.0

1.5

3.0

Index

c(0

, 0

.69

31

47

18

05

59

94

5,

1.0

98

61

22

88

66

81

1,

1.3

86

29

43

61

11

98

9,

1.6

09

43

79

12

43

41

, 1

.79

17

59

46

92

28

05

, 1

.94

59

10

14

90

55

31

, 2

.07

94

41

54

16

79

84

, 2

.19

72

24

57

73

36

22

, 2

.30

25

85

09

29

94

05

, 2

.39

78

95

27

27

98

37

, 2

.48

49

06

64

97

88

, 2

.56

49

49

35

74

61

54

, 2

.63

90

57

32

96

15

26

, 2

.70

80

50

20

11

02

21

, 2

.77

25

88

72

22

39

78

, 2

.83

32

13

34

40

56

22

, 2

.89

03

71

75

78

96

16

, 2

.94

44

38

97

91

66

44

)

6.2 Substitutionslogplot <- function(y, ylab = deparse(substitute(y))){ y <- log(y) plot(y, ylab = ylab)}logplot(1:19)

13

Page 14: Chapter 6: Computing on the language (R Language Definition)

5 10 15

0.0

1.5

3.0

Index

1:1

96.2 Substitutions

logplot <- function(y, ylab = deparse(substitute(y))){ ylab y <- log(y) plot(y, ylab = ylab)}logplot(1:19)

14

“ylab” をあらかじめ評価しておくと良い

Page 15: Chapter 6: Computing on the language (R Language Definition)

6.3 More on evaluation

> x <- 3> y <- 10> eval(quote(x+y), data.frame(x = 1:10), sys.frame(sys.parent())) [1] 11 12 13 14 15 16 17 18 19 20> eval(quote(x+y), sys.frame(sys.parent()))[1] 13

15

• eval 関数‒ “call” オブジェクトを評価するときに使用‒ どの“環境”で評価をするのかを指定可能– 例(親環境評価): eval(expr, sys.frame(sys.parent())

先にデータの値を使って評価してくれる

Page 16: Chapter 6: Computing on the language (R Language Definition)

6.4 Evaluation of expression objects

> ex <- expression(2 + 2, 3 + 4)> ex[[1]]2 + 2> ex[[2]]3 + 4> eval(ex)[1] 7

16

• Expression object(2.1.4 に記載あり )– 特殊な Language Object– Language object との違い

• 複数の Expression を保持( call object の list みたいなもん)• eval 関数に通したときのみ評価される

call object のリストっぽく扱える

最後に評価されたものが値として返ってくる(中で評価は全部されてる)

Page 17: Chapter 6: Computing on the language (R Language Definition)

6.4 Evaluation of expression objects

> eval(substitute(mode(x), list(x = quote(2 + 2))))[1] "numeric"

> eval(substitute(mode(x), list(x = expression(2 + 2))))[1] "expression"

17

• 前述の例は基本 quote({2 + 2; 3 + 4}) と同じ• Language object との違い

• eval 関数に通したときのみ評価される

再帰的にeval される

“ 直に” eval 関数に渡されない場合はexpression は評価されない

Page 18: Chapter 6: Computing on the language (R Language Definition)

6.4 Evaluation of expression objects> e <- quote(expression(2 + 2))> eexpression(2 + 2)> mode(e)[1] "call"> ee <- expression(2 + 2)> eeexpression(2 + 2)> mode(ee)[1] "expression"

18

expression を作る call object

vs普通の expression

Page 19: Chapter 6: Computing on the language (R Language Definition)

6.5 Manipulation of function calls

> f <- function(x, y, ...) sys.call()> f(y = 1, 2, z = 3, 4)f(y = 1, 2, z = 3, 4)> f <- function(x, y, ...) match.call()> f(y = 1, 2, z = 3, 4)f(x = 2, y = 1, z = 3, 4)

19

• 関数がどのように呼ばれたのかを見たい– sys.call 関数– match.call 関数

“2” が x に割り当てられているのがわかりにくい

※ 返り値は両方共 Call Object

“2” が x に割り当てられているのがわかりやすい

Page 20: Chapter 6: Computing on the language (R Language Definition)

6.5 Manipulation of function calls

vh> f <- function (formula, data, subset, weights, na.action, method = "qr", + model = TRUE, x = FALSE, y = FALSE, qr = TRUE, singular.ok = TRUE, + contrasts = NULL, offset, ...) + {+ cl <- match.call()+ mf <- match.call(expand.dots = FALSE)+ m <- match(c("formula", "data", "subset", "weights", "na.action", + "offset"), names(mf), 0L)+ mf <- mf[c(1L, m)]+ print(mf)+ mf$drop.unused.levels <- TRUE+ print(mf[[1L]])+ mf[[1L]] <- as.name("model.frame")+ print(mf)+ eval(mf, parent.frame())+ }

20

• match.call は同じ引数で違う関数を呼ばれる時によく使われる(例 :lm 関数の頭)

関数名だけ変更して評価

Page 21: Chapter 6: Computing on the language (R Language Definition)

6.5 Manipulation of function calls> f(y~x, data.frame(x=1:10, y = 1:10 + rnorm(10)))f(formula = y ~ x, data = data.frame(x = 1:10, y = 1:10 + rnorm(10)))fmodel.frame(formula = y ~ x, data = data.frame(x = 1:10, y = 1:10 + rnorm(10)), drop.unused.levels = TRUE) y x1 1.409984 12 3.925316 23 5.449060 34 4.462354 45 5.494868 56 6.283794 67 7.479154 78 8.675264 89 8.283814 910 9.259617 10

21

関数名変更前

関数名変更+項目追加

Page 22: Chapter 6: Computing on the language (R Language Definition)

6.5 Manipulation of function calls

> f <- function(x, y, ...) match.call(expand.dots = FALSE)> f(y = 1, 2, z = 3, 4)f(x = 2, y = 1, ... = list(z = 3, 4))> f(y = 1, 2, z = 3, 4)$...$z[1] 3[[2]][1] 4

22

• match.call の expand.dots を FALSE にすると”…”がひと固まりのリストとして扱われる

リストとして扱われる。特に f(y = 1, 2, z = 3, 4)$... <- NULL等として要らないものを消去する際に使用

Page 23: Chapter 6: Computing on the language (R Language Definition)

6.5 Manipulation of function calls• 関数呼び出しを作成する2つの関数

– call 関数– do.call 関数

• call 関数– 関数名と引数のリストから call object を生成

• do.call 関数– call 関数と似てるけど、こちら値を即評価– mode が list な引数に指定した関数を適用( data.frame の mode も list なんで適用可能)

23

Page 24: Chapter 6: Computing on the language (R Language Definition)

6.5 Manipulation of function calls

> f <- function(x, y, ...) sys.call()> f(y = 1, 2, z = 3, 4)f(y = 1, 2, z = 3, 4)> f <- function(x, y, ...) match.call()> f(y = 1, 2, z = 3, 4)f(x = 2, y = 1, z = 3, 4)

24

• 関数 Call を作成する2つの関数– call 関数– do.call 関数

“2” が x に割り当てられているのがわかりにくい

※ 返り値は両方共 Call Object

“2” が x に割り当てられているのがわかりやすい

Page 25: Chapter 6: Computing on the language (R Language Definition)

6.5 Manipulation of function calls> y <- 10.5> (e <- call("round", y))round(10.5)> eval(e)[1] 10> > x <- list(x = 1:5, y = 101:105, z = 1001:1005)> do.call("rbind", x) [,1] [,2] [,3] [,4] [,5]x 1 2 3 4 5y 101 102 103 104 105z 1001 1002 1003 1004 1005

25

do.call 関数で引数のリストを全て” rbind” 関数で結合し行列化

call 関数で call object を生成 & 評価

Page 26: Chapter 6: Computing on the language (R Language Definition)

6.6 Manipulation of functions• 関数・クロージャーを操作する関数が存在

1. body: 関数の中身 (expression) を返却2. formals: 関数の引数を返却3. environment: 関数の環境を返却

• 関数⇔リストの相互変換 – as.list: 関数 ⇒ リスト– as.function :リスト ⇒ 関数

26

Page 27: Chapter 6: Computing on the language (R Language Definition)

6.6 Manipulation of functions> f.original <- function(x){x + a}> f <- f.original> f(3) 以下にエラー f(3) : オブ

ジェクト ‘ a’ がありません

> body(f){ x + a}

> formals(f)$x> environment(f)<environment: R_GlobalEnv>> body(f) <- quote(5^x)> #body(f) <- expression(5^x)> ffunction (x) 5^x 関数の中身

を変更できる

例として使う関数

27

Page 28: Chapter 6: Computing on the language (R Language Definition)

6.6 Manipulation of functions> f(3)[1] 125> > f <- f.original> formals(f) <- alist(x = , a = 10)> ffunction (x, a = 10) { x + a}

> f(3)[1] 13> > f <- f.original> as.list(f)$x[[2]]{ x + a}

変更された関数5^3 = 125 として評価

alist( の結果)を formals に入れることで外から束縛

3(x) + 10(a) = 13と評価される

※alist はうまいこと”型”を割り振った” list” を作ってくれる関数28

Page 29: Chapter 6: Computing on the language (R Language Definition)

6.6 Manipulation of functions> as.function(as.list(f))function (x) { x + a}> > f <- as.function(alist(x = ,y = 2,x + y))> f(3)[1] 5

関数をリスト化した後、再関数化で元通り

alist で作成した list を関数化

29