Rを使ったデータサイエンス講座 視覚化編をやってみる Part.1 導入


入門編を終わって、大まかな操作は理解できるようになったかと思います。では、実際にどのようにデータを人に理解してもらえるようにするか、ということに取り組んでいく必要があります。
視覚化することは数字のまとまりを見せるよりもものすごく効果的に情報を伝えることができますが、誤ったまとめ方をすれば誤った情報を伝えてしまうことになります。どうやって正しく視覚化するのか、間違いに気づき修正していくのか、その辺をこの講座では学びます。

1.データの種類

データの種類も色々あると思うのですが、大まかにはcategoricalとnumericの2種類を扱います。

カテゴリーは第一回の米国の北東部、南部、中部、西部といった地域や性別、辛さのマイルド、ミディアム、ホット等です。順序付けできるものとできないものに分類します。統計学の教科書ではordinal dataと定義されている?すいません、読んだことないので、どうなのかわからず...。

数値には連続(continuous)と離散(descrete)があります。説明で言っていることがよく理解できなかったのですが、多くのグループに対して少ないケース数、例えば州に対して人口、殺人件数が~というような場合は離散とします。身長のようにデータの数がある程度多ければ適度にばらけていくのが連続になります。人が1日に吸うタバコの量とかで言うと、箱数と本数で表現できるかと思いますが、箱数に関してはcategoricalとnumericどちらともいえるようなものになります。

2.累積分布関数(CDF)のグラフを作る

まずはざっくりと男女比を見てみます。

#男女比を出す。
> prop.table(table(heights$sex))

Female   Male 
 0.227  0.773 

女性が少ないですけど、どんなグループのデータなんでしょうか?
もう一つ、身長の分布を表現する方法として
累積分布関数(cumulative distribution function)またはCDFというものがあります。累積分布関数は「身長○○以下の割合は何%か」という情報なので、「身長A以下の割合は何%か」「身長B以下の割合は何%か」2つの条件を使えば身長の割合に関するすべての情報を抽出することができます。
例)170cm以下の割合 - 169cm以下の割合 = 170cmの人の割合
ただ、累積分布関数は統計学では使うけど、データサイエンスの手法としてはあまり一般的ではないとのこと。理由はあまり情報として言いたいことが表現できないから。どちらかというとヒストグラムの方が情報を伝えやすくなります。ただ、ヒストグラムの場合は累積分布関数よりもデータに関する情報が少なくなっています。情報の伝えやすさのために詳細さの一部を切り捨てているとも言えます。

累積分布関数のグラフを作るには以下のような感じでやりますということでやってみました。

#最大値と最小値で100分割
> a <- seq(min(heights$height),max(heights$height), length = 100 )
#シーケンス内のエントリを平均するファンクションを作成
> cdf_function <- function(x){
+     mean(heights$height <= x)
+ }
#sapplyを使ってtable化※テーブルは間違ってるかも
> cdf_values <- sapply(a, cdf_function)
> plot(a, cdf_values)

むむむ、線にならないのか。

3.標準偏差と平均を求める

分析で最もメジャーなものといえば平均と標準偏差でしょう。Rではファンクションとして既に用意されているので以下のようにやれば簡単に求められます。

#男性のみの身長データを作成
> index <- heights$sex=="Male"
> x <- heights$height[index]
#作成したデータで平均と標準偏差を求める
> average <- mean(x)
> SD <- sd(x)
#出力してみる。
> c(average,SD)
[1] 69.31  3.61
#出力してみる。(項目名追加)
> c(average=average,SD=SD)
average      SD 
  69.31    3.61 

標準単位とは正規分布の中心からどれだけ離れているかということです。ほとんどのデータは±2の範囲に収まりますが、±3だとかなりレアケースになります。↑では平均と標準偏差を出しましたが、以下のファンクションで一発で出てきます。中身を見ると一つ一つのデータに対して標準単位が出てくるので中身はご自分で確認してみてください。

> z <- scale(x)

正規分布で中心からの距離によってどれだけの値を含むかのコマンドは以下になります。

> mean(abs(z) <2 )
[1] 0.95
> mean(abs(z) <3 )
[1] 0.991
> mean(abs(z) <1 )
[1] 0.76

ちなみに正規分布では1:0.68、2:0.95、3:0.997 になるとのことです。
今回のデータもそれに近しい値が出てるのではないでしょうか。

標準偏差からf(a)を求める式も紹介してくれました。pnorm です。
ちなみにf(a)は値がある位置までの累積数を割合で表したものです。例えばしたは70.5インチ以上の人の割合を求める場合です。
※pnormは値aよりも左の部分の面積(割合)を出すので1から引いています。

#70.5 
> 1 - pnorm(70.5, mean(x), sd(x))
[1] 0.371

これの本質的な意味としては標準偏差さえあれば実際のデータが無くてもいいということです。ただ、分析においては、十分なサンプル数が揃っているとは限らず、離散したデータで分析をしなければならないことも考えられます。

69インチから72インチの人がどの程度いるかの割合を求めるには以下の2通りがあります。だいたい同じと先生は言ってますが、なんで同じになるんでしょうか...。

x <- heights$height[heights$sex == "Male"]

#その1 meanを使って引き算 
mean(x <= 72) - mean(x <= 69)

#その2 meanをひとまとめにする
mean(x > 69 & x <= 72)

#その3 pnormを使う
pnorm(72, mean(x), sd(x)) - pnorm(69, mean(x), sd(x))

quantile というファンクションでもある、地点での累計を比率で求めることができます。25%、75%がそれぞれsummary()の1st Qu. 3rd Qu. と一致していることを確認してください。

> p <- seq(0.01, 0.99, 0.01)
> percentiles <- quantile(heights$height, p)

> summary(heights$height)
   Min. 1st Qu.  Median    Mean 3rd Qu.    Max. 
  50.00   66.00   68.50   68.32   71.00   82.68 

pnormとqnorm の関係は以下のようになります。

> qnorm(0.025)
[1] -1.959964
> pnorm(-1.96)
[1] 0.0249979
> theorical_quantiles <- qnorm(p, 69, 3)
> theorical_quantiles

qnorm にシーケンス(基本は100分割?)と中央値、標準偏差を与えてあげると正規分布に従った場合の理論値を出してくれます。

4.Quantile Plots

先ほど作成したシーケンスpとscale(x) を入れたz で以下のように理論値と実測値をそれぞれx軸y軸に取ってプロットします。

> observed_quantiles <- quantile(z, p) 
> theorical_quantiles <- qnorm(p)
> plot(theorical_quantiles, observed_quantiles)
> abline(0,1)

概ね実測値が理論値通りに分布していることが見て取れます。

5.グラフ化するときに揃える5つの部品

ちゃんと整ったグラフを作る際に必要なCOMPONENT(タイトルだと適当に部品と訳してしまいました)を確認していきます。登山する前に装備品の確認しっかりやる!みたいなノリです。

①データコンポーネント
当たり前ですが、ちゃんと扱える状態の整ったデータが必要になります。
②グラフの種類
散布図、棒グラフ、ヒストグラム、正規分布、q-qプロット、ボックスプロットどれにするか迷いますね。でも、ある程度どれでも使いこなせるべきです。
③マッピングコンポーネント
X軸、Y軸に何を設定するか。プロットのラベルに何を表示するか?プロットの色は?マッピングの定義は②のグラフの種類によって変わってきます。

そのほかにも重要なコンポーネントとして以下の2項目も考慮しておく必要があります。ここについては後で気づきがあれば書き足すかも。
④スケールコンポーネント
⑤ラベル、タイトル、凡例

第二回へ続く。

エクササイズ覚書

table() 一つの連続データを入れて、頻度を数えようとしたら、

x <- table(heights$height) 
sum(x == 1)

でいいらしい。項目を指定しなくていいのが意外だった。確かにheight自体の値とかいちいち参照しないというのはあるかもだが..。

library(HistData)
data(Galton)
x <- Galton$child
sd(x)
median(x)
mad(x)

mad はabsolute deviation らしい。