ハーバード大のWEB講座でRを使ったデータサイエンス入門をやってみる Part.3 Vectors & Sort


第一回第二回は基本的な使い方を学びました。これから本格的にデータサイエンスとしてのデータの扱い方を学んでいきます。多分。あと、自分は先生の言った英語を適当に意訳しているので大間違いな表現含まれるかもしれません。その辺は指摘あれば直していくようにします。

1.Vectorとは

データフレームの中にある一つのカラムに属するデータのかたまりをVectorと呼ぶそうです。データベースでカラムが5つあったらそれは5つのVectorがあるデータフレーム、と表現できます。
Vectorを手入力で作る場合は以下のように入力します。カッコの前につくCは「concatenate」の略です。連結とか連結体という意味のようなので、どちらかといえば後者が今使っている用途としてふさわしい訳なのかもしれません。

#数字のVector
> codes <- c(380,124,818)
#charのVector
> country <- c("italy","canada","egypt")
#数字とcharのVector ラベル付きデータ
> mix <- c(italy=380,canada=124,egypt=818)

手作業のデータで1~10まで打つとかはめんどくさいのでシーケンスというものもあるようです。自分が言った表現はともかく、よく使うファンクションなので覚えておきましょうと先生が言っています。

> seq(1,10)
 [1]  1  2  3  4  5  6  7  8  9 10

#1個飛ばしでのシーケンス
> seq(1,10,2)
[1] 1 3 5 7 9

次はSequence とか Vector の中身にアクセスしてみます。このページの初っ端で入れたmixの変数の2番目のデータを見てみます。

> mix[2]
canada 
   124 

#1番目から2番目のデータにアクセスする。
> mix[1:2]
 italy canada 
   380    124 

#項目のラベルでアクセスする。
> mix["canada"]
canada 
   124 

124でアクセスしようとしたりダブルクォーテーション忘れるとエラーになります。
複数データ取りたいときは以下のようにやります。念のため失敗したときのやり方も載せておきます。

#複数データ取るやり方
> mix[c("egypt","italy")]
egypt italy 
  818   380 

#ダメな例
> mix["egypt","italy"]
 mix["egypt", "italy"] でエラー:  次元数が正しくありません 

2.Vectorの中身を型変換する。もしくは勝手に型変換してくれる。

以下のように打鍵してみましょう。(なんとなく打鍵を使ってみたかった)

> x <- c(1,"canada",3)
> x
[1] "1"      "canada" "3"   
> class(x)
[1] "character"

Vectorは同じ型のセットなのでエラー起こるかと思いきや、3つの項目全てをcharacterとして値をセットしているようです。
次は数字で入れたデータをcharに意図的に変換してみます。

> x <- 1:5
> y <- as.character(x)
> y
[1] "1" "2" "3" "4" "5"

ダブルクォーテーションで囲まれているのは型がcharだからですね。値を割当するときに指定した型ですが、取りだす時も同様に型を指定できます。今度はダブルクォーテーションがないのでnumericになっています。

> as.numeric(y)
[1] 1 2 3 4 5

無理やり変換して失敗するとどうなるでしょう?例えばローマ字をnumericに変換してみます。

> x <- c("1","b","3")
> as.numeric(x)
[1]  1 NA  3
 警告メッセージ: 
 強制変換により NA が生成されました  

bは変換できないのでNAになりました。1と3はちゃんと変換してくれたようです。
先生は「NAなんてよく見るから心の準備しとけよ!」って言ってました。そうあれかし...。

この講座のテスト、やたらとシーケンスの使い方ばっかり問われました。その中でこれは説明されんとわからんぞ、と思ったのはシーケンスを等間隔に分割する以下コマンド。length.out = 3 数字を等間隔に3つ並べるようなシーケンスになります。どうやって使うんでしょうか?

x <- seq(0, 100, length.out = 3)
x
[1]   0  50 100

あと、問題が何を答えとして求めているのかわからないことが多々あり、何回か間違えました

x <- as.numeric(x)

3.Sortしてみる

今までは、データに対する操作は出力するか、型を変更するくらいだったのですがもう一つ重要な操作を今までやっていませんでした。並べ替えです。今回は例によって物騒なデータですが、アメリカの殺人件数をもとに安全な州ランキングを出してみたいと思います。

> library(dslabs)
> data(murders)
> sort(murders$total)
 [1]    2    4    5    5    7    8   11   12   12   16   19   21   22   27   32   36   38   53   63
[20]   65   67   84   93   93   97   97   99  111  116  118  120  135  142  207  219  232  246  250
[39]  286  293  310  321  351  364  376  413  457  517  669  805 1257

一行当たりのデータの個数はペインの幅で決まります。また、自分で作ったVectorを並べ替えると以下のようになります。

> x <- c(31, 4, 15, 92, 65)
> x
[1] 31  4 15 92 65
> sort(x)
[1]  4 15 31 65 92
> 

もう一つサラッと説明されたけど地味に意味が分からなかったものがorderです。Vectorを整列させてからindexで表記します。最後におまけとして順位付けのファンクションも入れました。

#xの中身を確認。整列してない。
> x
[1] 31  4 15 92 65

#Vectorを整列してindexを変数に割当て
> index <- order(x)

#indexの中身を確認
> index
[1] 2 3 1 5 4

#整列したindexと紐づけてxを出力
> x[index]
[1]  4 15 31 65 92

#Vectorの値を小さい順で順位づけ
> rank(x)
[1] 3 1 2 5 4

パッと見分かりにくいですが、入力された順番でIDが振られていることが確認できるはずです。一番小さい数字の4は2番目の入力値なので2と表現されています。2番目に小さい数字15は3番目の入力値です。なんでこんなことをするのかパッと思い浮かびません。以下のような感じで書くとわかりやすいかも。

[値] 31  4 15 92 65
[ID]  1  2  3  4  5
※これはコンソールでは出ません

4.ランキングしてみる。

州の名前でデータを先頭から10個出力してみます。どうもabc順でデータが作られているようですね。

> murders$state[1:10]
 [1] "Alabama"              "Alaska"               "Arizona"              "Arkansas"            
 [5] "California"           "Colorado"             "Connecticut"          "Delaware"            
 [9] "District of Columbia" "Florida"             
> murders$abb[1:10]
 [1] "AL" "AK" "AZ" "AR" "CA" "CO" "CT" "DE" "DC" "FL"

殺人の件数でランキングしたいので、まずは殺人の件数totalをorderして小さい順に並べます。
物騒な単語ばかり使っているのでQiitaにBANされそうな気がしてきました。

> index <- order(murders$total)
> murders$state[index]
 [1] "Vermont"              "North Dakota"         "New Hampshire"        "Wyoming"             
 [5] "Hawaii"               "South Dakota"         "Maine"                "Idaho"               
 [9] "Montana"              "Rhode Island"         "Alaska"               "Iowa"                
[13] "Utah"                 "West Virginia"        "Nebraska"             "Oregon"              
[17] "Delaware"             "Minnesota"            "Kansas"               "Colorado"            
[21] "New Mexico"           "Nevada"               "Arkansas"             "Washington"          
[25] "Connecticut"          "Wisconsin"            "District of Columbia" "Oklahoma"            
[29] "Kentucky"             "Massachusetts"        "Mississippi"          "Alabama"             
[33] "Indiana"              "South Carolina"       "Tennessee"            "Arizona"             
[37] "New Jersey"           "Virginia"             "North Carolina"       "Maryland"            
[41] "Ohio"                 "Missouri"             "Louisiana"            "Illinois"            
[45] "Georgia"              "Michigan"             "Pennsylvania"         "New York"            
[49] "Florida"              "Texas"                "California"         

講座だとabbで出力してましたがローマ字2文字で表記されてもどこだかわからないので名称で出力してみました。orderの使い方がわかってきた気がします。
続けて、最大値の取り方をやってみましょう。

#殺人件数の最大値をとる
> max(murders$total)
[1] 1257
#殺人件数が最大値のレコードのindexをi_maxに割当てる
> i_max <- which.max(murders$total)
> i_max
[1] 5
#i_maxのindexを名称と紐づけて出力
> murders$state[i_max]
[1] "California"

最後の締めに行ってましたが、sort order は小さい順に並べてるのは同じです。ただ出力してみると値そのもの、indexと別の形で表現されているということなので、そこをおさえておきましょう。orderは結構使う頻度高くなりそうな気がします。

テストで一番困ったのはstates でdefineせよみたいなことが書いてるのが、何を意味してるのかいまいちわからなかったのですが、

states <- murders$state

すればいいだけでした。まずは割当て、ですね。英語話すときに結構重要なポイントで単数形と複数形をしっかり使い分けよう!というのがあるのですが、正直自分レベルの英語力だと単数も複数も同じ単語として見ちゃうんですよね。なのでスッキリ腑に落ちてこないです。
あと、もう一つ困ったのが、ランク順に並べる、というところですが、以下のようにやるようです。

#小さい順に並べたindexを取得する
ind <- order(murders$population)

#普通のデータフレーム
my_df <- data.frame(states, ranks)

#ランキング順に並べたデータフレームを作る
my_df <- data.frame(states = states[ind], ranks = ranks[ind])
True or False のロジカル型でind に割当
ind <- is.na(na_example)
# TRUEの数(N/A)を数える
sum(ind)

第4回へ続きます)