やっちろ.Rの発表資料

会場なう。ということで、資料を置いておきます。

やっちろ.R in 熊本

今日のAgenda

  • 自己紹介
    • Tsukuba.Rについて
  • 事前調査
  • Rのぐぐり方、効率がよい(と思われる)勉強の仕方
  • Rのデータ構造とそれに関する関数
    • ベクトル、行列、データフレーム、リスト
    • 因子型、層別分析
  • apply family

はじめまして!!

  • id:syou6162
    • 吉田康久
    • please call me syou!!
  • 筑波大学院の修士一年生
  • Tsukuba.Rを運営している中の人

普段使っている言語

  • R
  • Ruby
  • C++

Tsukuba.Rについて

  • できた理由
  • RubyKaigi
    • 当日スタッフで参加


Rubyのコミュニティ楽しそう!!

  • Rにもこういうコミュニティがあったらいいなあ
  • RubyKaigi打ち上げ
    • Ruby札幌++
  • じゃあ、自分で作るか
    • Tsukuba.Rでけた!!

事前調査【頻度編】

  • まだRのインストールしてな(ry
  • Rのインストールはしてある
  • 週一回くらいの頻度では使っている
  • 週一回くらいの頻度では使っている
  • ほぼ毎日使っている

事前調査【Rの知識編】

  • ぶっちゃげ何も知らな(ry
  • read.csvとかでファイルを読めることくらいは知っている
  • plotとかすると何かできることを知っている
  • Rにおける基本的なデータ構造を知っている
  • 総称関数が分かる
  • 自分でパッケージ書いたことがある
  • Cによる拡張を書いたことがある

事前調査【統計知識編】

  • データの読み書き、plotくらいはやったことがある
  • 大学なりどこかで回帰分析くらいは勉強した記憶がある人
  • 統計、データマイニング、機械学習を勉強したことがある、または研究している

ご協力ありがとうございます

Rの勉強会でよく聞かれること

  • 「Rってぐぐりづらいよね」
  • 「アルファベット一文字のプログラミング言語使ってる人って(ry」

Rのぐぐり方

  • Rでの検索の方法
  • Rの勉強の仕方

まとめ

  • Rに聞く
  • Rでのkeywordを覚える
  • ハブサイトを押さえる

R

  • RのことはRに聞け
  • 分からないことはぐぐらずともRに聞く

keyになる関数

  • ?hoge
  • help("hoge")
  • example(hoge)

「?hoge」

  • hogeに関することを調べる
    • データに関すること
    • 関数に関すること

「example(hoge)」

  • どんなんかは何となく分かった
  • 実例が見たい
  • そんな時に

その他

  • example(example)とかすればいいと思います
  • help.search("foo")
  • demo(graphics)

関数定義を見る

  • 関数名をそのままtype
  • predict.lm
  • 大体はこれでおk

余談

  • 総称的関数
    • cf.methods("predict")
  • RにおけるOOPを実現

見れない関数もある

  • predict.arとか
    • 「 エラー: オブジェクト "predict.ar" は存在しません 」
  • 存在しないんじゃなくて、公開されていない→隠蔽されている

隠蔽されている関数のことも見たい

  • getAnywhere("predict.ar")

Rでのkeywordを覚える

  • 基本的なデータ構造やデータ型
  • 基本的な関数とか
  • 質問がしやすくなる(人とかgoogleとか)
  • この手のは本で勉強するとよいかも
    • あとで説明

本の紹介

  • あさましいリンクを張って(ry

The R Tips―データ解析環境Rの基本技・グラフィックス活用集

The R Tips―データ解析環境Rの基本技・グラフィックス活用集

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

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

データによるプログラミング―データ解析言語Sにおける新しいプログラミング

データによるプログラミング―データ解析言語Sにおける新しいプログラミング

Rプログラミングマニュアル (新・数理工学ライブラリ 情報工学)

Rプログラミングマニュアル (新・数理工学ライブラリ 情報工学)

Rによるデータサイエンス-データ解析の基礎から最新手法まで

Rによるデータサイエンス-データ解析の基礎から最新手法まで

ハブサイトを押さえる

というわけで、ここから本題

  • Agenda
    • Rのデータ構造、それに関連する便利な関数とかを紹介
    • "Rらしい"ところを説明する予定

データ構造

  • ベクトル
  • 行列
  • リスト
  • データフレーム
  • 因子

ベクトル

mydata <- c(1,2,3,4,5,6,7,8,9,10)

最小単位がベクトル

> 1
[1] 1
> is.vector(1)
[1] TRUE

Rの格言

  • 「意味のあるときは常に、意味の無いときも常にベクトル化を心がけよ」
    • ベクトル志向の関数が色々ある
    • 登場する度に紹介

規則的データの生成

  • Rubyの1..10みたいな
> 1:10
 [1]  1  2  3  4  5  6  7  8  9 10

ベクトルへのアクセスの方法

  • []
  • シーケンスを投げると、部分ベクトルにして返してくれる
  • ベクトルのインデックスが0からではなく1から始まるところが慣れないところかも
> mydata
 [1]  1  2  3  4  5  6  7  8  9 10
> mydata[5]
[1] 5
> mydata[3:5]
[1] 3 4 5

アクセス方法にもいろいろある

  • 論理値でTRUEのところだけを返す
> mydata[mydata > 3]
[1]  4  5  6  7  8  9 10
> mydata > 3
 [1] FALSE FALSE FALSE  TRUE  TRUE  TRUE  TRUE  TRUE  TRUE  TRUE

まだまだあるよ、アクセス方法

  • 負の引数を取ると、そこを除いてベクトルにして返す
    • 末尾のほうを見る言語に慣れている人はややこしく感じるところかも
  • []の中にc関数で負の値を入れておくと、複数個を取り除くこともできる
    • perlとかとは違う
> mydata[-10]
[1] 1 2 3 4 5 6 7 8 9
> mydata[-1]
[1]  2  3  4  5  6  7  8  9 10
> mydata[c(-1,-2)]
[1]  3  4  5  6  7  8  9 10

行列

  • matrix関数
  • ベクトルを行列に変換
  • 列から順に決まっていく
> matrix(mydata,2,5)
     [,1] [,2] [,3] [,4] [,5]
[1,]    1    3    5    7    9
[2,]    2    4    6    8   10

埋めていく順番

  • byrow=Tをやると行から埋めていくことができる
> matrix(mydata,2,5,byrow=T)
     [,1] [,2] [,3] [,4] [,5]
[1,]    1    2    3    4    5
[2,]    6    7    8    9   10

すでにあるベクトルを束ねる

  • cbind
  • rbind
> a <- c(1,2,3,4)
> b <- c(5,6,7,8)
> c <- c(9,10,11,12)
> d <- cbind(a,b,c)
> d
     a b  c
[1,] 1 5  9
[2,] 2 6 10
[3,] 3 7 11
[4,] 4 8 12

行列へのアクセス方法

  • これまた[]を使う
  • 列ごと、行ごとの表示も可
  • 「-」で取り除いたやつを返すのはベクトルのときと一緒
> d[2,3]
[1] 10
> d[2,]
 a  b  c
 2  6 10
> d[,3]
[1]  9 10 11 12
> d[c(-2,-4),]
     a b  c
[1,] 1 5  9
[2,] 3 7 11

行列の基本演算

  • 行列作って、足し算
  • 直感的
> a <- matrix(c(1,2,3,4),2,2,byrow=T)
> b <- matrix(c(1,2,3,4),2,2,byrow=T)
> a+b
     [,1] [,2]
[1,]    2    4
[2,]    6    8

積がやっかい

  • 「*」にしちゃうと積にならないよ
  • とりあえず誰もが最初にはまるところ
> a*b
     [,1] [,2]
[1,]    1    4
[2,]    9   16

積を求めたいときは「%*%」を使うべし

> a%*%b
     [,1] [,2]
[1,]    7   10
[2,]   15   22

逆行列を求める

  • solve関数
> solve(a)
     [,1] [,2]
[1,] -2.0  1.0
[2,]  1.5 -0.5

行列式

  • det関数
> det(a)
[1] -2

固有値

  • 簡単
  • 取り出し方は後で説明
    • リストでできる
> eigen(a)
$values
[1]  5.3722813 -0.3722813

$vectors
           [,1]       [,2]
[1,] -0.4159736 -0.8245648
[2,] -0.9093767  0.5657675

データフレーム

  • 行列に数値以外のものを入れたテーブル形式のデータ型

  • とりあえずデータフレームにいれたいベクトルを用意
> ID1 <- c(1,2,3,4,5)
> VISIT1 <- c(10,20,30,10,50)
> SEX1 <- c("F","M","M","F","F")
> WEIGHT <- c(30,20,90,40,30)

データフレームを作る

  • data.frame関数
> A <- data.frame(id=ID1,vit=VISIT1,sex=SEX1,w=WEIGHT)
> A
  id vit sex  w
1  1  10   F 30
2  2  20   M 20
3  3  30   M 90
4  4  10   F 40
5  5  50   F 30
> summary(A)
       id         vit     sex         w     
 Min.   :1   Min.   :10   F:3   Min.   :20  
 1st Qu.:2   1st Qu.:10   M:2   1st Qu.:30  
 Median :3   Median :20         Median :30  
 Mean   :3   Mean   :24         Mean   :42  
 3rd Qu.:4   3rd Qu.:30         3rd Qu.:40  
 Max.   :5   Max.   :50         Max.   :90  

リスト

  • ベクトルや配列は似たようなデータ構造をまとめて束ねたようなもの
  • リストは異なるデータ構造を束ねたもの
  • いろんな種類のベクトルをまとめてもよし
  • List in Listでも構わない

  • ベクトルと文字列と行列を束ねてみる
> list(c(1,2,3,4),"Yasuhisa Yoshida",matrix(1:4,2,2))
[[1]]
[1] 1 2 3 4

[[2]]
[1] "Yasuhisa Yoshida"

[[3]]
     [,1] [,2]
[1,]    1    3
[2,]    2    4

リストへのアクセス

  • ベクトルとはちょっと違う
  • [[]]でアクセス
  • []でもいいけど、返ってくる結果がリストになっていてちょっと複雑
  • それ以降の要素についてはベクトルとかと同じ
> list <- list(c(1,2,3,4),"Yasuhisa Yoshida",matrix(1:4,2,2))
> list[[1]]
[1] 1 2 3 4
> list[[2]]
[1] "Yasuhisa Yoshida"
> list[[3]]
     [,1] [,2]
[1,]    1    3
[2,]    2    4
> list[[3]][1,]
[1] 1 3

リストは結構難しい><

  • 返ってきた結果が予想と違うこととかが結構ある
  • 例:ベクトルだと思って処理しようとしたら、実はリストが返ってきててうまくいかない
  • 対処法
    • mode関数
    • class関数
    • データ構造が何かを教えてくれる関数

  • 1列目の1番目の値を取ってきたい
  • うまくいかない。。。
  • うまくいかない理由をmode関数で調べる
> list[1]
[[1]]
[1] 1 2 3 4

> list[1][1]
[[1]]
[1] 1 2 3 4

> list[[1]]
[1] 1 2 3 4
> list[[1]][1]
[1] 1
> mode(list)
[1] "list"
> mode(list[[1]])
[1] "numeric"
> mode(list[1])
[1] "list"

リストの要素には名前を付けることができる

  • 数字で覚えるのは面倒
  • 名前でアクセスできるようにしよう
    • hashの"ような"もの
  • 「$」でアクセスするよ
> list <- list(vec=c(1,2,3,4),name="Yasuhisa Yoshida",matrix=matrix(1:4,2,2))
> list
$vec
[1] 1 2 3 4

$name
[1] "Yasuhisa Yoshida"

$matrix
     [,1] [,2]
[1,]    1    3
[2,]    2    4

> list$name
[1] "Yasuhisa Yoshida"
> list$matrix[2,2]
[1] 4

Rでlistがどのように使われているか

  • 回帰分析をRにやらせる
  • 赤の線
plot(cars$dist,cars$speed)
abline(lm(speed~dist,data=cars),col="red")

Quartz 2 [*]

これの内容がどうなっているか

> summary(lm(speed~dist,data=cars))

Call:
lm(formula = speed ~ dist, data = cars)

Residuals:
    Min      1Q  Median      3Q     Max 
-7.5293 -2.1550  0.3615  2.4377  6.4179 

Coefficients:
            Estimate Std. Error t value Pr(>|t|)    
(Intercept)  8.28391    0.87438   9.474 1.44e-12 ***
dist         0.16557    0.01749   9.464 1.49e-12 ***
---
Signif. codes:  0***0.001**0.01*0.05 ‘.’ 0.1 ‘ ’ 1 

Residual standard error: 3.156 on 48 degrees of freedom
Multiple R-squared: 0.6511,	Adjusted R-squared: 0.6438 
F-statistic: 89.57 on 1 and 48 DF,  p-value: 1.490e-12 

リストの中身を見る

  • str関数
> str(summary(lm(speed~dist,data=cars)))
List of 11
 $ call         : language lm(formula = speed ~ dist, data = cars)
 $ terms        :Classes 'terms', 'formula' length 3 speed ~ dist
  .. ..- attr(*, "variables")= language list(speed, dist)
  .. ..- attr(*, "factors")= int [1:2, 1] 0 1
  .. .. ..- attr(*, "dimnames")=List of 2
  .. .. .. ..$ : chr [1:2] "speed" "dist"
  .. .. .. ..$ : chr "dist"
  .. ..- attr(*, "term.labels")= chr "dist"
  .. ..- attr(*, "order")= int 1
  .. ..- attr(*, "intercept")= int 1
  .. ..- attr(*, "response")= int 1
  .. ..- attr(*, ".Environment")=<environment: R_GlobalEnv> 
  .. ..- attr(*, "predvars")= language list(speed, dist)
  .. ..- attr(*, "dataClasses")= Named chr [1:2] "numeric" "numeric"
  .. .. ..- attr(*, "names")= chr [1:2] "speed" "dist"
 $ residuals    : Named num [1:50] -4.62 -5.94 -1.95 -4.93 -2.93 ...
  ..- attr(*, "names")= chr [1:50] "1" "2" "3" "4" ...
 $ coefficients : num [1:2, 1:4] 8.2839 0.1656 0.8744 0.0175 9.474 ...
  ..- attr(*, "dimnames")=List of 2
  .. ..$ : chr [1:2] "(Intercept)" "dist"
  .. ..$ : chr [1:4] "Estimate" "Std. Error" "t value" "Pr(>|t|)"
 $ aliased      : Named logi [1:2] FALSE FALSE
  ..- attr(*, "names")= chr [1:2] "(Intercept)" "dist"
 $ sigma        : num 3.16
 $ df           : int [1:3] 2 48 2
 $ r.squared    : num 0.651
 $ adj.r.squared: num 0.644
 $ fstatistic   : Named num [1:3] 89.6 1 48
  ..- attr(*, "names")= chr [1:3] "value" "numdf" "dendf"
 $ cov.unscaled : num [1:2, 1:2] 7.68e-02 -1.32e-03 -1.32e-03 3.07e-05
  ..- attr(*, "dimnames")=List of 2
  .. ..$ : chr [1:2] "(Intercept)" "dist"
  .. ..$ : chr [1:2] "(Intercept)" "dist"
 - attr(*, "class")= chr "summary.lm"

リストの要素を取得

  • 「$」でアクセスする
> summary(lm(speed~dist,data=cars))$coefficients
             Estimate Std. Error  t value     Pr(>|t|)
(Intercept) 8.2839056 0.87438449 9.473985 1.440974e-12
dist        0.1655676 0.01749448 9.463990 1.489836e-12

因子型

  • factor型とも

irisのデータでやってみる

  • あやめのデータ
  • よく使われるデータ
  • よい性質を持っているから

irisデータ

  • それぞれ50個ずついるよ
> head(iris$Species)
[1] setosa setosa setosa setosa setosa setosa
Levels: setosa versicolor virginica
> class(iris$Species)
[1] "factor"
> summary(iris$Species)
    setosa versicolor  virginica
        50         50         50

層別にSepal.Lengthの長さを調べてみる

  • tapply(データ, 因子型のデータ, 関数)
> tapply(iris$Sepal.Length,iris$Species,mean)
    setosa versicolor  virginica 
     5.006      5.936      6.588 

ヒストグラムを書いてみよう

> library(lattice)
> histogram(~Sepal.Length,data=iris)

できあがり

  • 普通のヒストグラムと一緒じゃん
  • 違うよ、全然違うよ

層別にヒスとグラムを書けるのがlatticeライブラリのhistgram

  • 分布が違うね、とかいうことが分かる
> histogram(~Sepal.Length|Species,data=iris)

層別に分析するのはよく使う

  • 顧客を色んな軸(性別、年齢、etc)で切って、データを分析しやすくする
    • 主成分分析で次元削減した軸で、層別の分析etc

層別に統計量を出してくれるのがby関数

  • 第一引数に求めたいデータ
  • 第二引数に層別するもとのデータ
  • 第三引数に求めたい統計量
    • mean
    • var
> by(iris$Sepal.Length,iris$Species,summary)
INDICES: setosa
   Min. 1st Qu.  Median    Mean 3rd Qu.    Max.
  4.300   4.800   5.000   5.006   5.200   5.800
------------------------------------------------------------
INDICES: versicolor
   Min. 1st Qu.  Median    Mean 3rd Qu.    Max.
  4.900   5.600   5.900   5.936   6.300   7.000
------------------------------------------------------------
INDICES: virginica
   Min. 1st Qu.  Median    Mean 3rd Qu.    Max.
  4.900   6.225   6.500   6.588   6.900   7.900

行列やデータフレームを持ってくることもできる

  • それぞれの列に対して層別された統計量を求める
> by(x[1:4],iris$Species,mean)
iris$Species: setosa
Sepal.Length  Sepal.Width Petal.Length  Petal.Width
       5.006        3.428        1.462        0.246
------------------------------------------------------------
iris$Species: versicolor
Sepal.Length  Sepal.Width Petal.Length  Petal.Width
       5.936        2.770        4.260        1.326
------------------------------------------------------------
iris$Species: virginica
Sepal.Length  Sepal.Width Petal.Length  Petal.Width
       6.588        2.974        5.552        2.026

層別で頻度を集計する

  • 条件を付けたりすることができる
> xtabs(~Species,data=iris,Sepal.Width>3)
Species
    setosa versicolor  virginica
        42          8         17

散布図を層別で書いてみる

  • 色分け
  • 他にもいろいろオプションはあるよ
  • ヘルプで見てね
> xyplot(Sepal.Length~Sepal.Width,data=iris,col=as.integer(iris$Species))

配布する資料が白黒だったら。。。

  • そもそも散布図を3つ書けばよい
  • 「|」の後に因子データを持ってくる
> xyplot(Sepal.Length~Sepal.Width|Species,data=iris)

できあがり

余談

R Graphical Manual

データ型の話はこの辺でとりあえず

apply familyの紹介

まとめ

  • Rらしいコードを書くならapply family
  • ベクトル、行列、データフレーム、リストに対して何か作用させるようなもの
  • applyとtapplyは覚えて帰って損ないよ!!

apply familyって?

  • lispのapplyのようなもの
  • Rを使いこなす上では割けては通れない関数群
    • Rはインタプリタ的なものなので、for文をそのまま回すと遅いことがある
    • ベクトルを中心に考えるRとしては、Rらしいコードが書ける

で、applyファミリーって何?

  • ベクトル、行列、データフレーム、リストに対して何か作用させるようなもの

例で説明

apply

  • 行や列に対していっぺんに何かを作用させる
    • 意味分かんない
> cars
> mean(cars$speed)
[1] 15.4
> mean(cars$dist)
[1] 42.98

一つ一つめんどくさい

  • この例ならsummary(cars)とかでできる
  • 自分で作った関数とかsummaryがやってくれないやつを一辺にやりたい
    • 例えば、自分で平均と標準偏差を返す関数を作ったとか
  • そういう時にapply関数

実例

  • 第一引数にデータフレーム
    • 行列でもいい
  • 第二引数は1か2
    • 1は行
    • 2は列
> apply(cars,2,mean)
speed  dist
15.40 42.98

lapplyとsapply

  • 本質的には同じような働きをする関数
  • 返す結果がリストか、ベクトル(行列)かという違いくらい

lapply

  • リストに対して、ある関数をそれぞれ適用させるための関数
  • データフレームっぽいのならapplyでいい
    • 長さが整っていないものならlapplyかsapplyを使いましょう
  • lapplyは返す結果がlist
> a <- 1:10
> b <- letters[1:26]
> x <- list(a,b)
> lapply(x,summary)
[[1]]
   Min. 1st Qu.  Median    Mean 3rd Qu.    Max.
   1.00    3.25    5.50    5.50    7.75   10.00

[[2]]
   Length     Class      Mode
       26 character character

sapply

  • lapplyの返す結果がベクトルのやつ
  • 返ってきた結果を使いまわすんだったら、こっちのほうが使い易いかもしれない
> x <- list(a = 1:10, beta = exp(-3:3), logic = c(TRUE,FALSE,TRUE,FALSE))
> sapply(x, mean)
       a     beta    logic
5.500000 4.535125 0.500000

mapply

  • (複数個の)ベクトルのそれぞれの要素をある関数に適用させることができる関数
  • RubyやPerlのmapと思ってもらえばいいです
> mapply(function(x,y){x+y},1:10,11:20)
 [1] 12 14 16 18 20 22 24 26 28 30
> mapply(function(x){paste("R:",x,sep="")},1:10)
 [1] "R:1"  "R:2"  "R:3"  "R:4"  "R:5"  "R:6"  "R:7"  "R:8"  "R:9"  "R:10"

mapplyを使わないでやることもできる

  • ベクトル中心の考え方
> paste("R:",1:10,sep="")
 [1] "R:1"  "R:2"  "R:3"  "R:4"  "R:5"  "R:6"  "R:7"  "R:8"  "R:9"  "R:10"

tapply

  • 因子とか層別で分析したいときに重宝する関数
    • こいつはapplyとtapplyくらいは覚えて帰って損しないと思うよ
> library(MASS)
> attach(quine)
> tapply(Days,Age,mean)
      F0       F1       F2       F3
14.85185 11.15217 21.05000 19.60606
> tapply(Days,list(Sex,Age),mean)
        F0       F1       F2       F3
F 18.70000 12.96875 18.42105 14.00000
M 12.58824  7.00000 23.42857 27.21429
> tapply(Days,list(Sex,Age),mean)
        F0       F1       F2       F3
F 18.70000 12.96875 18.42105 14.00000
M 12.58824  7.00000 23.42857 27.21429

まとめ

  • Rらしいコードを書くならapply family
  • ベクトル、行列、データフレーム、リストに対して何か作用させるようなもの
  • applyとtapplyは覚えて帰って損ないよ!!

全体でのまとめ

  • 自己紹介
    • Tsukuba.Rについて
  • 事前調査
  • Rのぐぐり方、効率がよい(と思われる)勉強の仕方
  • Rのデータ構造とそれに関する関数
    • ベクトル、行列、データフレーム、リスト
    • 因子型、層別分析
  • apply family