51
Rあんなときこんなとき ~いつか役に立つ(かもしれない)Tips~ 2011年3月5日 第12回 TokyoR @sfchaos

Rあんなときこんなとき(tokyo r#12)

  • Upload
    sfchaos

  • View
    4.589

  • Download
    8

Embed Size (px)

DESCRIPTION

 

Citation preview

Page 1: Rあんなときこんなとき(tokyo r#12)

Rあんなときこんなとき~いつか役に立つ(かもしれない)Tips~

2011年3月5日

第12回 TokyoR

@sfchaos

Page 2: Rあんなときこんなとき(tokyo r#12)

1

本発表の趣旨

� Rに初めて触れた頃,それまでに使っていたCやC++に比べて利便性が高いと思ったものの,お作法など分からないことがたくさんありました.

� 本発表では,特に私がRを触れた初期の頃に調べたりつまづいたポイントを中心に,6つのTipsについてクイズ形式で議論したいと思います.

Page 3: Rあんなときこんなとき(tokyo r#12)

2

アジェンダ

1. 自己紹介

2.クイズで議論! RのTips

3. まとめ

Page 4: Rあんなときこんなとき(tokyo r#12)

3

アジェンダ

1. 自己紹介

2.クイズで議論! RのTips

3. まとめ

Page 5: Rあんなときこんなとき(tokyo r#12)

4

自己紹介

� TwitterID: @sfchaos

� 出身地: 埼玉県

� 職業:コンサルタント

� 数年間,金融工学のモデル構築・データ解析

� 最近,大規模データ解析に着手(Hadoop/Mahout)

� 趣味:登山

� 学生時代の専攻は物理・応用数学(非線形力学系・カオス)

Page 6: Rあんなときこんなとき(tokyo r#12)

5

� 私とR� データ解析の仕事に携わりRを使い始めた.

� 最近はRでの大規模データ解析に興味がある.

20082007 2009 2010 2011

データ解析(金融工学)

大規模データ解析

Rの基礎とプログラミング技法

R Tips(Webサイト)

RjpWiki(Webサイト)

Software fordata analysis

CRANマニュアル

Page 7: Rあんなときこんなとき(tokyo r#12)

6

� 私とR� データ解析の仕事に携わりRを使い始めた.

� 最近はRでの大規模データ解析に興味がある.

20082007 2009 2010 2011

データ解析(金融工学)

大規模データ解析

Rの基礎とプログラミング技法

R Tips(Webサイト)

RjpWiki(Webサイト)

Software fordata analysis

CRANマニュアル

今日の発表の範囲

Page 8: Rあんなときこんなとき(tokyo r#12)

7

アジェンダ

1. 自己紹介

2.クイズで議論! RのTips

3. まとめ

Page 9: Rあんなときこんなとき(tokyo r#12)

8

問題1【ファイルの読み込み】

Page 10: Rあんなときこんなとき(tokyo r#12)

9

� 自分で作成した関数を格納したファイルを読み込んでいます.

� 量が多くて大変です.

� どうすれば良いでしょうか.

> source("a.r")> source("b.r")> source("c.r")> source("d.r")...> source("z.r")

Page 11: Rあんなときこんなとき(tokyo r#12)

10

【答え】

読み込み用の関数を別途作成する

Page 12: Rあんなときこんなとき(tokyo r#12)

11

readfile.rreadfile <- function(){ fn.all <- c("a.r", "b.r", (中略), "z.r") for (fn in fn.all) { source(fn) cat(fn, "\n") }}

> source("readfile.r")> readfile()

� 読み込み用関数を作成

� 次のコマンドを実行

Page 13: Rあんなときこんなとき(tokyo r#12)

12

readfile.rreadfile <- function(){ fn.all <- c("a.r", "b.r", (中略), "z.r") for (fn in fn.all) { source(fn) cat(fn, "\n") }}

> source("readfile.r"); readfile()

� 読み込み用関数を作成

� 次のコマンドを実行

実は1行で書ける!

Page 14: Rあんなときこんなとき(tokyo r#12)

13

(ご参考)

� 毎回,必ず読み込むファイルがある場合は,作業フォルダ直下の.Rprofileファイルの.First関数に記述しておくことも一つの手.

.Rprofile

.First <- function(){ inputdir <- "C:\Users\sfchaos\lib\R" fn.all <- paste(inputdir, c("lib.r", "util.r")) for (fn in fn.all) { source(fn) cat(fn, "\n") }}

C:\Users\sfchaos\lib\R\lib.rC:\Users\sfchaos\lib\R\util.r>

Page 15: Rあんなときこんなとき(tokyo r#12)

14

あまり派手にやると,

不要な関数を読み込んで時間がかかるので

おススメしません!

Page 16: Rあんなときこんなとき(tokyo r#12)

15

第2問【データ・ファイルの管理】

Page 17: Rあんなときこんなとき(tokyo r#12)

16

� Rを使用してデータ解析を行っています.

� 次のコードは,データをファイルから読み込み,データの一部を変更し,ファイルに書き出しています.

� 実行すると,望みどおりの動作をします.

� このコードには問題はないでしょうか?

> getwd()[1] "C:/Users/sfchaos/TokyoR/R_Tips(TokyoR#12)/work"> my.iris <- read.table("iris.csv", sep=",") # データの入力> my.iris[1:5, 1] <- 3> write.table(my.iris, "my_iris.csv", sep=",") # データの出力

Page 18: Rあんなときこんなとき(tokyo r#12)

17

【答え】

問題あり!!

入力データ格納フォルダ,

作業フォルダ,

出力データ格納フォルダが

すべて同じフォルダになっている

Page 19: Rあんなときこんなとき(tokyo r#12)

18

� データ解析は次のフローに従って行う.

入力データ 解析 出力データ

Page 20: Rあんなときこんなとき(tokyo r#12)

19

� フォルダも対応して別々に作ると良い.

入力データ 解析 出力データ

data work output

Page 21: Rあんなときこんなとき(tokyo r#12)

20

� では,入力データ格納フォルダ("data"フォルダ)のデータを作業フォルダで扱うには?

� 2つの方法がある.1)入力データ格納フォルダで作成したオブジェクトを作業フォルダで読み込む

2)作業フォルダで,関数の引数に読み込む入力データのファイル名を指定する

Page 22: Rあんなときこんなとき(tokyo r#12)

21

1) 入力データ格納フォルダで作成したオブジェクトを作業フォルダで読み込む

> getwd()[1] "C:/Users/sfchaos/TokyoR/R_Tips(TokyoR#12)/data"> my.iris <- read.table("iris.csv", sep=",")> assign("my.iris", my.iris, pos=1) # 現在の環境にオブジェクトを作成> quit # 保存してから終了する

入力データ格納フォルダでの作業

Page 23: Rあんなときこんなとき(tokyo r#12)

22

> getwd()[1] "C:/Users/sfchaos/TokyoR/R_Tips(TokyoR#12)/work" > attach("../data/.RData")> ls()character(0)> search()[1] ".GlobalEnv" "file:../data/.RData"...> ls(pos=2)[1] "my.iris"

作業フォルダでの作業

Page 24: Rあんなときこんなとき(tokyo r#12)

23

work/hoge.rhoge <- function(fn="../data/my_iris.csv"){ my.iris <- read.table(fn, sep=",") (後略)}

> source("hoge.r")> hoge()

2) 作業フォルダで,関数の引数に読み込む入力  データのファイル名を指定する

Page 25: Rあんなときこんなとき(tokyo r#12)

24

work/hoge2.rhoge2 <- function(datadir="../data/", fn="my_iris.csv"){ my.iris <- read.table(paste(datadir, fn, sep=""), sep=",") (後略)}

「入力データフォルダ名」と「入力データファイル名」を分離

データフォルダを複数作成する場合は,こうすると良い

Page 26: Rあんなときこんなとき(tokyo r#12)

25

第3問【NA/NaN/Infの判定】

Page 27: Rあんなときこんなとき(tokyo r#12)

26

� データの中に存在するNAやNaNに加えて,Infも調べようとしています.

� ところが,is.na関数やis.nan関数を使ってもInfは検出できません.

� NA, NaNも調べられて,なおかつInfも調べるためにはどうすれば良いでしょうか?

> x[1] 1 5 NA 3 NaN 9 6 Inf> is.nan(x)[1] FALSE FALSE FALSE FALSE TRUE FALSE FALSE FALSE> is.na(x)[1] FALSE FALSE TRUE FALSE TRUE FALSE FALSE FALSE

Page 28: Rあんなときこんなとき(tokyo r#12)

27

【答え】

is.finite関数を使用する

Page 29: Rあんなときこんなとき(tokyo r#12)

28

> x[1] 1 5 NA 3 NaN 9 6 Inf> is.finite(x)[1] TRUE TRUE FALSE TRUE FALSE TRUE TRUE FALSE

Page 30: Rあんなときこんなとき(tokyo r#12)

29

第4問【総称型関数】

Page 31: Rあんなときこんなとき(tokyo r#12)

30

� Rにも慣れてきて,パッケージの関数の中身を確認したいと思うようになりました.

� ところが,次の表示が出て中身が確認できません.

� 中身を確認する関数を調べるにはどうすれば良いでしょうか?

> install.packages("randomForest")> library(randomForest)> randomForestfunction (x, ...) UseMethod("randomForest")<environment: namespace:randomForest>

Page 32: Rあんなときこんなとき(tokyo r#12)

31

【答え】

methods関数で調べる

Page 33: Rあんなときこんなとき(tokyo r#12)

32

� 総称型関数とは?(plot関数の例)

> x <- runif(10)> class(x)[1] "numeric"> print(x) [1] 0.03060976 0.78413098 0.79548343 0.15108456 0.70864539 0.10040559 [7] 0.18165933 0.90008356 0.46093800 0.52717448> y <- sample(1:10, 100, replace=TRUE)> y.tbl <- table(y)> class(y)[1] "table"> print(y.tbl) 1 2 3 4 5 6 7 8 9 10 11 16 13 8 11 15 9 7 8 2

ベクトルでも行列でも同じprint関数で表示できる!

Page 34: Rあんなときこんなとき(tokyo r#12)

33

> printfunction (x, ...) UseMethod("print")<environment: namespace:base>

print関数

Page 35: Rあんなときこんなとき(tokyo r#12)

34

> print.defaultfunction (x, digits = NULL, quote = TRUE, na.print = NULL, print.gap = NULL, right = FALSE, max = NULL, useSource = TRUE, ...) { noOpt <- missing(digits) && missing(quote) && missing(na.print) && missing(print.gap) && missing(right) && missing(max) && missing(useSource) && length(list(...)) == 0L .Internal(print.default(x, digits, quote, na.print, print.gap, right, max, useSource, noOpt))}<environment: namespace:base>

ベクトル用print関数

Page 36: Rあんなときこんなとき(tokyo r#12)

35

> print.tablefunction (x, digits = getOption("digits"), quote = FALSE, na.print = "", zero.print = "0", justify = "none", ...) { xx <- format(unclass(x), digits = digits, justify = justify) if (any(ina <- is.na(x))) xx[ina] <- na.print if (zero.print != "0" && any(i0 <- !ina & x == 0) && all(x == round(x))) xx[i0] <- sub("0", zero.print, xx[i0]) if (is.numeric(x) || is.complex(x)) print(xx, quote = quote, right = TRUE, ...) else print(xx, quote = quote, ...) invisible(x)}<environment: namespace:base>

table用print関数

Page 37: Rあんなときこんなとき(tokyo r#12)

36

� 総称型関数はmethods関数で調べられる

> methods(randomForest)[1] randomForest.default* randomForest.formula*

Non-visible functions are asterisked

Page 38: Rあんなときこんなとき(tokyo r#12)

37

第5問【総称型関数(続き)】

Page 39: Rあんなときこんなとき(tokyo r#12)

38

� 第4問で調べるべき関数が分かったので,中身を表示させようとしました.

� ところが,次の表示が出ます.

� どうすれば良いでしょうか?

> randomForest.default エラー: オブジェクト 'randomForest.default' がありません> randomForest.formula エラー: オブジェクト 'randomForest.formula' がありません

Page 40: Rあんなときこんなとき(tokyo r#12)

39

【答え】

マスクされた関数の中身は,

getFromNamespace関数,

またはパッケージ名:::関数名で

表示する

Page 41: Rあんなときこんなとき(tokyo r#12)

40

� getFromNamespace関数

> getFromNamespace("randomForest.default", "randomForest")function (x, y = NULL, xtest = NULL, ytest = NULL, ntree = 500, mtry = if (!is.null(y) && !is.factor(y)) max(floor(ncol(x)/3), 1) else floor(sqrt(ncol(x))), replace = TRUE, classwt = NULL, cutoff, strata, sampsize = if (replace) nrow(x) else ceiling(0.632 * nrow(x)), nodesize = if (!is.null(y) && !is.factor(y)) 5 else 1, maxnodes = NULL, importance = FALSE, localImp = FALSE, nPerm = 1, proximity, oob.prox = proximity, norm.votes = TRUE, do.trace = FALSE, keep.forest = !is.null(y) && is.null(xtest), corr.bias = FALSE, keep.inbag = FALSE, ...) { 中略}<environment: namespace:randomForest>

Page 42: Rあんなときこんなとき(tokyo r#12)

41

� パッケージ名:::関数名

> randomForest:::randomForest.defaultfunction (x, y = NULL, xtest = NULL, ytest = NULL, ntree = 500, mtry = if (!is.null(y) && !is.factor(y)) max(floor(ncol(x)/3), 1) else floor(sqrt(ncol(x))), replace = TRUE, classwt = NULL, cutoff, strata, sampsize = if (replace) nrow(x) else ceiling(0.632 * nrow(x)), nodesize = if (!is.null(y) && !is.factor(y)) 5 else 1, maxnodes = NULL, importance = FALSE, localImp = FALSE, nPerm = 1, proximity, oob.prox = proximity, norm.votes = TRUE, do.trace = FALSE, keep.forest = !is.null(y) && is.null(xtest), corr.bias = FALSE, keep.inbag = FALSE, ...) { 中略}<environment: namespace:randomForest>

Page 43: Rあんなときこんなとき(tokyo r#12)

42

� そもそもrandomForest.default関数がrandomForestパッケージにあることをどのように知ればよいか?

> randomForestfunction (x, ...) UseMethod("randomForest")<environment: namespace:randomForest>

Page 44: Rあんなときこんなとき(tokyo r#12)

43

� 入っているパッケージが分からないときは?> getAnywhere("randomForest.default")A single object matching ‘randomForest.default’ was foundIt was found in the following places registered S3 method for randomForest from namespace randomForest namespace:randomForestwith value

function (x, y = NULL, xtest = NULL, ytest = NULL, ntree = 500, mtry = if (!is.null(y) && !is.factor(y)) max(floor(ncol(x)/3), 1) else floor(sqrt(ncol(x))), replace = TRUE, classwt = NULL, cutoff, strata, sampsize = if (replace) nrow(x) else ceiling(0.632 * nrow(x)), nodesize = if (!is.null(y) && !is.factor(y)) 5 else 1, maxnodes = NULL, importance = FALSE, localImp = FALSE, nPerm = 1, proximity, oob.prox = proximity, norm.votes = TRUE, do.trace = FALSE, keep.forest = !is.null(y) && is.null(xtest), corr.bias = FALSE, keep.inbag = FALSE, ...) { 中略}<environment: namespace:randomForest>

Page 45: Rあんなときこんなとき(tokyo r#12)

44

第6問【デバッグ】

Page 46: Rあんなときこんなとき(tokyo r#12)

45

� パッケージをインストールして,関数がどのような動きをするか確めます.

� インプットとアウトプットだけでなく,途中でどのような処理をしているか知りたくなりました.

� しかし,パッケージの関数の中に直接cat関数やprint関数を埋め込むことは出来ません.

� 仕方ないので,パッケージの関数をコピーして,catやprintを埋め込みました.

� 何か問題はあるでしょうか?

Page 47: Rあんなときこんなとき(tokyo r#12)

46

work/my_randomForest.rmy.randomForest <- function (x, ...) UseMethod("my.randomForest")

my.randomForest.default <- functionfunction (x, y = NULL, xtest = NULL, ytest = NULL, ntree = 500, mtry = if (!is.null(y) && !is.factor(y)) max(floor(ncol(x)/3), 1) else floor(sqrt(ncol(x))), replace = TRUE, classwt = NULL, cutoff, strata, sampsize = if (replace) nrow(x) else ceiling(0.632 * nrow(x)), nodesize = if (!is.null(y) && !is.factor(y)) 5 else 1, maxnodes = NULL, importance = FALSE, localImp = FALSE, nPerm = 1, proximity, oob.prox = proximity, norm.votes = TRUE, do.trace = FALSE, keep.forest = !is.null(y) && is.null(xtest), corr.bias = FALSE, keep.inbag = FALSE, ...) { addclass <- is.null(y) cat(addclass, "\n") classRF <- addclass || is.factor(y) print(classRF) if (!classRF && length(unique(y)) <= 5) { warning("The response has five or fewer unique values. Are you sure you want to do regression?") } (中略)}

Page 48: Rあんなときこんなとき(tokyo r#12)

47

【答え】

関数の中身を調べたいときは,

デバッグ用の関数を使う

Page 49: Rあんなときこんなとき(tokyo r#12)

48

� デバッグモードの設定

> randomForest(iris[, -5])Browse[2]> debug: addclass <- is.null(y)Browse[2]> ndebug: classRF <- addclass || is.factor(y)Browse[2]> addclass[1] TRUE

� デバッグモードでの実行

> debug(randomForest:::randomForest.default)

Page 50: Rあんなときこんなとき(tokyo r#12)

49

アジェンダ

1. 自己紹介

2.クイズで議論! RのTips

3. まとめ

Page 51: Rあんなときこんなとき(tokyo r#12)

50

� Rは使いやすい統計ツールですが,効率的に使うためのテクニックがいろいろとあります.

� 自分で試行錯誤したり,RjpWikiなどで調べることが「自分にとって使いやすい」Tipsをためることにつながります.

� Rに少し慣れてきたら,「Rの基礎とプログラミング技法」は必ず読みましょう!