今までの記事は以下になります。
第一回
第二回
第三回
第四回
講座も4パートに分かれたうちの3つ目に入りました。これからは本格的な使い方を教えるよ!って前回の終わりに先生が言ってたので期待していきたいと思います。
#1.論理演算子を使用してベクトルにインデックスを付ける
以下のように10万人当たりの殺人件数が0.71人以下の州を抽出してみます。ちなみに0.71はイタリアの統計のようです。
#0.71以下の値かどうかを判定する式を入れる。
> index <- murder_rate <= 0.71
> index
[1] FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE TRUE FALSE FALSE FALSE TRUE
[17] FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE TRUE FALSE FALSE
[33] FALSE FALSE TRUE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE TRUE FALSE FALSE
[49] FALSE FALSE FALSE
#TRUEの値を持つエントリを州名で表示する。(日本語微妙)
> murders$state[index]
[1] "Hawaii" "Iowa" "New Hampshire" "North Dakota" "Vermont"
ちなみにTRUEじゃない方の場合はmurders$state[!index]です。続けて2つの論理演算式を&でつなげてみます。地域が西で、10万人あたりの殺人件数が1の州を求めるには以下のようにします。
> west <- murders$region == "West"
> safe <- murder_rate <= 1
> index <- safe & west
> murders$state[index]
[1] "Hawaii" "Idaho" "Oregon" "Utah" "Wyoming"
#2.indexのファンクション
インデックスのファンクションにはshich match %in% があるとのことでした。では、いったいどんな使い方をするのでしょうか?
まずはwhichです。TRUEのエントリのIDを返しているようです。
> x <- c(FALSE,TRUE,FALSE,TRUE,TRUE,FALSE)
> which(x)
[1] 2 4 5
> index <- which(murders$state =="Massachusetts")
> index
[1] 22
> murder_rate[index]
[1] 1.802179
which使わなくてもいいんじゃね?と思ったのですが、使わないと以下のようになります。なるほど。
> index <- murders$state =="Massachusetts"
> index
[1] FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE
[17] FALSE FALSE FALSE FALSE FALSE TRUE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE
[33] FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE
[49] FALSE FALSE FALSE
次はmatchを使ってみます。
> index <- match(c("New York","Florida","Texas"),murders$state)
> index
[1] 33 10 44
#インデックスのエントリIDを使って10万人あたりの殺人件数を表示
> murder_rate[index]
[1] 2.667960 3.398069 3.201360
#州名を持つVectorを作成する。
> murder_state <- murders$state
#インデックスのエントリIDを使って州名を表示
> murder_state[index]
[1] "New York" "Florida" "Texas"
最後のファンクション%in%は非常に使えるらしいです。比較して同じ値がVectorに含まれていたらTRUEっぽいです。
> x <- c("a","b","c","d","e")
> y <- c("a","d","f")
> y %in% x
[1] TRUE TRUE FALSE
> x %in% y
[1] TRUE FALSE FALSE TRUE FALSE
ほかにも、州名と州名でないものを混ぜて、州名のVectorと比較してみます。ワシントンだけが正解のようです。
> c("Boston","Dakota","Washington") %in% murders$state
[1] FALSE FALSE TRUE
#3.もう少し高度な操作
タイトルがモヤっとしてますが...。より高度な分析をするために便利なパッケージで「dplyr」を紹介してくれました。子音しかないから読めないっ!けどめげずにパッケージをインストールします。
> library(dplyr)
次のパッケージを付け加えます: ‘dplyr’
以下のオブジェクトは ‘package:stats’ からマスクされています:
filter, lag
以下のオブジェクトは ‘package:base’ からマスクされています:
intersect, setdiff, setequal, union
#4.便利なファンクションx4
今回使う主要なコマンドを紹介します。多分dplyrを入れたから使えるようになったと思われます。
データテーブルにカラムを足したり一部?を変更するコマンドとして「mutate」があるそうです。多分ミュータントの動詞です。行をサブセット化してフィルターをかけるのは「filter」、行をサブセット化して特定のデータを選択することを「select」、そして結果をファンクションからファンクションへ送るコマンドとして「%>%」で使用することができるパイプオペレーター、以上の4つを使って学習していきましょう。
> murders <- mutate(murders,rate=total/population*100000)
何が便利かというとdefineしないままに計算に使っているってところらしいです。viewしたりhead したりでカラムが追加できていることが確認できます。楽ですね。
> View(murders)
> head(murders)
state abb region population total rate
1 Alabama AL South 4779736 135 2.824424
2 Alaska AK West 710231 19 2.675186
3 Arizona AZ West 6392017 232 3.629527
4 Arkansas AR South 2915918 93 3.189390
5 California CA West 37253956 1257 3.374138
6 Colorado CO West 5029196 65 1.292453
次はfilterです。毎度のイタリアの0.71 より殺人事件発生率が低い州を抽出してみます。
> filter(murders, rate <=0.71)
state abb region population total rate
1 Hawaii HI West 1360301 7 0.5145920
2 Iowa IA North Central 3046355 21 0.6893484
3 New Hampshire NH Northeast 1316470 5 0.3798036
4 North Dakota ND North Central 672591 4 0.5947151
5 Vermont VT Northeast 625741 2 0.3196211
Filterは&でつなげて複数の条件で絞り込めます。
※%in%は下の方を参照してください。
my_states <- filter(murders , region %in% c("Northeast" , "West") & rate <= 1)
次はselectです。あれ?Filterこれだけ?まあいいか、murderのデータフレームから一部のカラムだけを抽出して新規テーブルを作ります。そのあとfilterで再度0.71以下の州を出します。さっきよりカラム減ってますね。
> new_table <- select(murders,state,region,rate)
> filter(new_table, rate <=0.71)
state region rate
1 Hawaii West 0.5145920
2 Iowa North Central 0.6893484
3 New Hampshire Northeast 0.3798036
4 North Dakota North Central 0.5947151
5 Vermont Northeast 0.3196211
select( の次の最初にはオブジェクトを書くことをしっかりと覚えておきましょう。ただ、このやり方はベーシックなものなので、dplyrを使えばもっとスムーズにデータの操作ができます。
> murders %>% select(state,region,rate) %>% filter(rate <= 0.71)
state region rate
1 Hawaii West 0.5145920
2 Iowa North Central 0.6893484
3 New Hampshire Northeast 0.3798036
4 North Dakota North Central 0.5947151
5 Vermont Northeast 0.3196211
一個前のselect → filter したものと同じ結果が一行で取得できました。ただ、これが便利なのかちょっと不明。例が悪いのかな...。%>%って打ちにくいんですよね。select(のオブジェクト入れるってのもいきなりひっくり返されるし。
#5.データフレームをつくる
データを操作するにはデータフレームを使いこなす必要があります。基本的には以下のような感じなのでそれほど難しくないですが、一つ気を付けることがあります。それはデータフレームに入れたcharacterがFactorに変換されてしまうことです....
> grades <- data.frame(names=c("John","Juan","Jean","Yao"),exam_1 = c(95,80,90,85),exam_2 = c(90,85,85,90))
> grades
names exam_1 exam_2
1 John 95 90
2 Juan 80 85
3 Jean 90 85
4 Yao 85 90
> class(grades$names)
[1] "character"
...解散!
※おそらくバージョン変わってそうならないようになったということだと思います。
> grades <- data.frame(names=c("John","Juan","Jean","Yao"),exam_1 = c(95,80,90,85),exam_2 = c(90,85,85,90),stringsAsFactors = TRUE)
> class(grades$names)
[1] "factor"
> grades <- data.frame(names=c("John","Juan","Jean","Yao"),exam_1 = c(95,80,90,85),exam_2 = c(90,85,85,90),stringsAsFactors = FALSE)
> class(grades$names)
[1] "character"
念のためFactor型にもできることを確認しておきました。
自分の備忘のためのメモですが、講座の小テストでなるほど、と思ったのがrankの使い道です。rank カラムを追加する問題があって、なんでそんなことするのかな?と思ったらTOP5とかを表示するときに便利だから、のようです。というよりそうするのが唯一の正解なのかも。
> murders <- mutate(murders, rate = total/population * 100000, rank = rank(-rate))
> filter(murders, rank <= 5)
あと、%in% です。こちらは条件を複数同時に使いたいときに便利なようです。
#RegionがNortheastとWestだけのデータフレームmurders_nwを作る
> murders_nw <- filter(murders, region %in% c("Northeast" , "West"))
#murders_nw のデータ数を数える。
> nrow(murders_nw)
[1] 22
こんな感じでひたすら条件つなげていく感じでできます。murders 書くのも最初の一回だけですし、dplyr 使うと便利かなと思います。ただ、自信ないうちにいきなりこんな長いの書くとイザ間違ってた時に悲惨なので、少しずつ実行しながらつなげていくのが良いかと。
my_states <- murders %>% mutate(rate = total/population * 100000, rank =rank(-rate)) %>% filter(region %in% c("Northeast", "West") & rate <= 1) %>% select(state, rate, rank)
第六回へ続きます