タグ:map

第4章は統計を扱います。


今回も「シロート統計学」のハルさんとコラボレーションすることとなりました。


シロート統計学はEZRを使った統計分析をわかりやすく解説されています。


 


第4章はシロート統計学で使われていたEZRをRで行うとどうなるのか?といった視点で進めていきます。


今回使うデータもハルさんのサイトと同じものを使わせでいただく事になりました。それぞれ見比べることで参考にしてみてください!


今回は一元配置分散分析を紹介します



まず一元配置分散分析(ANOVA)についてはハルさんのサイトをご参照ください。



また1.準備〜4.データの読み込みまでは【4-1】Rでt検定を行う方法と全く同じ流れになります。
もし1〜4まででわからない部分があれば確認してみてください。

 

1.準備

第4章は毎回ExcelデータをダウンロードしてRを使うのでプロジェクトで管理して行うことを勧めています。

 

ここではR練習というプロジェクトを作り、Excelファイルを入れるためのdataフォルダを作っています。
これを前提に次から進めていきます。
スクリーンショット 2019-10-20 7.54.14


2.スクリプトファイルの作成

次にRのコードを書くためのスクリプトファイルを作ります。

スクリーンショット 2019-11-08 14.32.40


3.データのダウンロード

今回もハルさんのサイトのデータを使わせていただきます。

デモデータ(ANOVA)

この章ではRを使ってダウンロードしています。


download.file(url = “ファイルのURL”,
        destfile = “保存したい場所/ファイル名”)
urlはデモデータで右クリック → リンクのアドレスをコピー
destfileは保存場所と保存のファイル名を指定します。


実際のコードは以下になります。
前回のコードのURL(" "の中)とdestfileのdata/以降を変更するだけでOKです。
#データのダウンロード
url <- "https://haru-reha.com/wp-content/uploads/2018/05/demo-anova.xlsx"
destfile = "data/demo-anova.xlsx"

download.file(url, destfile)
スクリーンショット 2019-11-08 14.30.34

dataフォルダにダウンロードできたことを確認します。


4.データの読み込み

データを読み込みます。
今回は【4-0】第4章を進めていく上での準備で行った方法で進めます。

View Fileでデータを確認します。

スクリーンショット 2019-11-08 14.24.20



データが入っているセルを確認します。
B2からC22までデータが入っています(B2:C62と表記)
スクリーンショット 2019-11-08 14.26.26


次にImport Datasetでデータを取り込みます。
スクリーンショット 2019-11-07 23.37.11

Import画面ではName, Sheet,Rangeを指定します。

Name:ハルさんのサイトではgripでしたがgrip_anovaとします(大文字・小文字は別物とされます)
Sheet:このExcelは1つしかデータがないのでDefaultのままでOK
Range:先ほど確認したB2:C62

スクリーンショット 2019-11-07 23.40.57



Importボタンを押す前に右にあるコードをコピーしスクリプトファイルに貼り付けることも忘れずに行います。
library(readxl)
grip_anova <- read_excel("data/demo-anova.xlsx", 
                         range = "B2:C62")
View(grip_anova)

データが正しく入っていることを確認します。
スクリーンショット 2019-11-08 14.36.37

これでデータの取り込みは完成です。

5.正規分布の確認

ハルさんのサイトに沿って正規分布の確認を行います。

正規分布の確認は【4-1】Rでt検定を行う方法で紹介しています。
以下のコードがイメージできない場合はまずこちらの記事をご参照ください。



まずヒストグラムで分布を確認します。
1つずつグラフを作るのは手間がかかるので、まとめてグラフを作ります。

ヒストグラムはgeom_histgram関数を使います。
グラフが重なっていると見にくいのでfacet.gridでカテゴリーごとにグラフを分けます。
facet.gridに関しては【3-4】Rのggplot2でヒストグラムを作るgeom_histogram関数で紹介しています。

library(tidyverse)
ggplot(data = grip_anova) +
  geom_histogram(aes(x = grip, fill = category), bins = 5) +
  facet_grid(category ~ .)
スクリーンショット 2019-11-08 15.27.34

6.シャピロ・ウィルク検定
次にハルさんのサイトでは正規性の検定を行っています。
正規性の検討はshapriro.test関数3つのカテゴリーそれぞれに行う必要があります。

今回はsplit関数map関数を使いまとめて行ってみます。
下の図は【4-1】Rでt検定を行う方法で使った方法ですが今回のコードと見比べてみてください。
コードがほとんど同じです。コードを使うと他でも役に立つことがわかります。

スクリーンショット 2019-10-26 22.42.55

grip_anova %>% 
  split(.$category) %>% 
  map(~shapiro.test(.$grip))
スクリーンショット 2019-11-08 16.19.14

まとめて結果が出ました。すべて正規分布であることが棄却されませんでした。


7.等分散性の確認

次に等分散性の確認を行います。

3群以上で等分散性を検定するにはBartlett検定を使います。

bartlett.test(数値の列 ~ グループ)

data = を使えば$は必要ありません。どちらでも大丈夫です。
bartlett.test(grip_anova$grip ~ grip_anova$category)

bartlett.test(grip ~ category, data = grip_anova)



8.分散分析(ANOVA)を行う

それでは本題の一元配置分散分析と多重比較を行います。

実は一元配置分散分析と重回帰分析(t検定も)は同じ分析方法です(詳しく知りたい方は一般線形モデルで検索してみてください)。出てきた結果を分散分析の形式で表示するか重回帰分析の結果で表示するかの違いだけです。
そのため一元配置分散分析を行うには分散分析のaov関数重回帰分析のlm関数で行います。
ただその後に行う多重比較ではlm関数が使えないものもあるので基本はaov関数で大丈夫です。

どちらの関数もまずモデルを作りサマリーを表示するというのが一般的な流れです。

全体的な流れは以下の通りです。
sumamry関数だけ結果の表示が変わるので注意が必要です。
スクリーンショット 2019-11-11 20.05.02


aov関数の場合

モデル名:model_grip_anova(好きな名前でOK)
従属変数:grip
独立変数:category
データ名:grip_anova
model_grip_anova <- aov(grip ~ category, data = grip_anova)
summary(model_grip_anova)
スクリーンショット 2019-11-11 20.09.17


lm関数の場合

モデル名:model_grip_lm(好きな名前でOK)
従属変数:grip
目的変数:category
データ名:grip_anova
model_grip_lm <- lm(grip ~ category, data = grip_anova)
summary.aov(model_grip_lm)
スクリーンショット 2019-11-11 20.10.45



結果はどちらもEZRと同じになりました。


9.多重比較を行う

ハルさんのサイトでは多重比較でTukeyを紹介していますが他も紹介します。
Tukeyだけ関数が違います。
スクリーンショット 2019-11-11 22.18.55


Tukeyの場合
Tukeyの場合は先程のaov関数の結果を使います。
lm関数の結果は使えませんので注意が必要です。
TukeyHSD(model_grip_anova)
スクリーンショット 2019-11-11 22.26.49


Bonferroniの場合
pairwise.t.test関数はモデルの結果を使いません。

pairwise.t.test(目的変数 , グループ, p.adjust.method = “〇〇“)

ちなみにdata = の形式は使えないので$を使います。
pairwise.t.test(grip_anova$grip, grip_anova$category, p.adjust.method = "bonferroni")
スクリーンショット 2019-11-11 22.24.31



Holmの場合
pairwise.t.test(grip_anova$grip, grip_anova$category, p.adjust.method = "holm")
スクリーンショット 2019-11-11 22.24.40


Hochbergの場合
pairwise.t.test(grip_anova$grip, grip_anova$category, p.adjust.method = "hochberg")
スクリーンショット 2019-11-11 22.24.46



10.まとめ
今回は一元配置分散分析を紹介しました。
今回は割愛しましたが、一元配置分散分析を行うときはlongデータである必要があります。

Excelでデータ収集するときに注意するか、wideデータの場合はlongデータに直してから分析を行ってください。

longデータとwideデータについてはで【2-5】Rでデータを集計するのに便利なlongデータとgather関数
紹介しています。

次回はKruskal-Wallis検定を行います。



11.今回のコード
今回使ったコードのまとめになります。
#データのダウンロード
url <- "https://haru-reha.com/wp-content/uploads/2018/05/demo-anova.xlsx"
destfile = "data/demo-anova.xlsx"

download.file(url, destfile)

library(readxl)
grip_anova <- read_excel("data/demo-anova.xlsx", 
                         range = "B2:C62")
View(grip_anova)


#正規分布の確認
library(tidyverse)
ggplot(data = grip_anova) +
  geom_histogram(aes(x = grip, fill = category), bins = 5) +
  facet_grid(category ~ .)


grip_anova %>% 
  split(.$category) %>% 
  map(~shapiro.test(.$grip))

#Bartlett検定

bartlett.test(grip_anova$grip ~ grip_anova$category)

bartlett.test(grip ~ category, data = grip_anova)

#一元配置分散分析
#aov関数の場合
model_grip_anova <- aov(grip ~ category, data = grip_anova)
summary(model_grip_anova)

#lm関数の場合
model_grip_lm <- lm(grip ~ category, data = grip_anova)
summary.aov(model_grip_lm)

#多重比較
#Tukey
TukeyHSD(model_grip_lm)

#Bonferroni
pairwise.t.test(grip_anova$grip, grip_anova$category, p.adjust.method = "bonferroni")

#Holm
pairwise.t.test(grip_anova$grip, grip_anova$category, p.adjust.method = "holm")

#Hochberg
pairwise.t.test(grip_anova$grip, grip_anova$category, p.adjust.method = "hochberg")



全記事の目次はこちらをご参照ください






第4章は統計を扱います。


今回「シロート統計学」のハルさんとコラボレーションすることとなりました。


ハルさん、ありがとうございます!


シロート統計学はEZRを使った統計分析をわかりやすく解説されています。




第4章はシロート統計学で使われていたEZRをRで行うとどうなるのか?といった視点で進めていきます。


今回使うデータもハルさんのサイトと同じものを使わせでいただく事になりました。それぞれ見比べることで参考にしてみてください!


今回はt検定を紹介します



まずt検定についてはハルさんのサイトをご参照ください。

 



1.準備

第4章は毎回ExcelデータをダウンロードしてRを使うのでプロジェクトで管理して行うことを勧めています。



ここではR練習というプロジェクトを作り、Excelファイルを入れるためのdataフォルダを作っています。
これを前提に次から進めていきます。


2.スクリプトファイルの作成

次にRのコードを書くためのスクリプトファイルを作ります。

スクリーンショット 2019-10-25 12.15.42

完成です。
スクリーンショット 2019-10-25 12.18.51


3.データのダウンロード

今回はハルさんのサイトのデータを使わせていただきます。

デモデータ(t検定)

これをダウンロードしてdataフォルダに入れればいいのですが実はRでできてしまいます
download.file関数を使います。" "を忘れないようにしてください。

url <- "https://haru-reha.com/wp-content/uploads/2018/03/demo-t-test.xlsx"
destfile = "data/demo-t-test.xlsx"

download.file(url, destfile)

以下説明します。

download.file(url = “ファイルのURL”,
        destfile = “保存したい場所/ファイル名”)


urlはデモデータで右クリック → リンクのアドレスをコピー

destfileは保存場所と保存のファイル名を指定します。
保存場所は今回プロジェクトを使っているのでR練習フォルダになります。加えてdata/を付け足すことでR練習フォルダ内にあるdataフォルダという意味になります。
ファイル名は自由に決められますが今回は元のファイルと同じにしました。拡張子も忘れないようにしましょう。

もしプロジェクトを使っていなければ保存場所はgetwd関数で出てきたフォルダになります。
getwd関数の()には何も入れません。

getwd()


この方法を使う最大のメリットは、次回使うExcelデータはurlの部分を変えるだけでできてしまうことです。毎回右クリックでアドレスを保存 → 保存したファイルを指定したところに移動させて・・・といった手作業必要ありません。こういった作業もRで行っていくことでRにも早く慣れてくると思います。



4.データの読み込み

データを読み込みます。
今回は【4-0】第4章を進めていく上での準備で行った方法で進めます。

View Fileでデータを確認します。
スクリーンショット 2019-10-25 14.07.12

今回は握力のデータです。A群とB群を比較します。
ただA1にデータが入っていません。実際にはB2からC62までデータが入っていることを確認します。
スクリーンショット 2019-10-25 14.11.22

次はImport Datasetを選びます。
スクリーンショット 2019-10-25 14.07.18

ポイントは2つです。
①データの名前(変数名)を付ける
何でもいいのですが今回はハルさんのサイトと同じgripにしました。

②読み込む範囲を指定する
今回A1からのデータではないので先程確認したB2からC62を指定します。
B2:C62のように左上と右下を:でつなげます
スクリーンショット 2019-10-25 14.17.12


そして右下にコードが自動的に作られます。Importを押せば完了なのですが、このコードをコピーしスクリプトに貼り付けておけば1年たった後でも同じことができます。EZRでもスクリプトを保存することができないわけではないのですが、再現性(後でしても、他の人がしても同じ事ができる)を保つためにもこういったコードを残しておく習慣をつけるようにしましょう。
スクリーンショット 2019-10-25 14.19.26


コードの一番下にあるView関数を使うことでRStudio内でもデータの確認ができます。このタブを消してもデータに影響はありません。もう1回View関数を使えばまた表示できます。
スクリーンショット 2019-10-25 14.28.00

View関数はEZRで言う表示と同じです(下図はハルさんのサイトより。比べてみてください)



これでデータの取り込みは完了です!



5.データの要約

ハルさんは次にデータの要約をしています。
EZRでのデータの要約と全く同じ機能はないですが、第2章で紹介したtidyverseパッケージのgroup_by関数とsummarize関数が使えます。group_by関数とsummarize関数に関してはこちらで紹介しています。

%>%やgroup_by関数、summarize関数はtidyverseパッケージに含まれていますのでtidyverseパッケージを呼び出します。もしtidyverseパッケージを全く使ったことが無い方はパッケージをインストールします。1度でも使ったことがあれば次の1行は必要ありません。

install.packages("readxl")

実際のコードは以下になります。イメージ図も添付します。

library(tidyverse)
grip %>% group_by(category) %>% summarize(平均 = mean(grip), 標準偏差 = sd(grip), '0%' = quantile(grip, 0), '25%' = quantile(grip, 0.25), '50%' = quantile(grip, 0.5), '75%' = quantile(grip, 0.75), '100%' = quantile(grip, 1), n = n())

スクリーンショット 2019-10-25 20.52.13

スクリーンショット 2019-10-26 7.55.30


これでA群とB群のデータのばらつきを確認することができます。
ちなみにこのコードをコピーして色がついた箇所を変更すれば他の場面でも使えます!

このままでもいいのですが、データ要約は後でグラフ作成に使うのでgrip_summaryという名前をつけます。

grip_summary <- 
grip %>% group_by(category) %>% summarize(平均 = mean(grip), 標準偏差 = sd(grip), '0%' = quantile(grip, 0), '25%' = quantile(grip, 0.25), '50%' = quantile(grip, 0.5), '75%' = quantile(grip, 0.75), '100%' = quantile(grip, 1), n = n())


6.正規性の確認

次に正規性の確認を行います。ハルさんのサイトではヒストグラムを作成しました。
ヒストグラムの作り方はこちらで紹介しています。


ハルさんのヒストグラムは棒が5本だったので同じ形にするようbins = 5とします。
A群とB群の棒を横に並べるときはposition = "dodge"を使います。
ggplot()で行を変える時は %>% ではなく + を使うので注意してください。

ggplot(data = grip) + 
  geom_histogram(aes(x = grip, fill = category), position = "dodge", bins = 5) 

スクリーンショット 2019-10-25 20.55.06



加えてシャピロ・ウィルク検定も紹介されています。シャピロ・ウィルク検定はshapriro.test関数を使います。
ただA群とB群それぞれで行いますのでgrip$gripの列をA群とB群に分ける必要があります。

shapiro.test(grip$grip[category == "A"])
shapiro.test(grip$grip[category == "B"])



データの中で特定の条件だけを抜き出すには[ ]を使います。



ハルさんのサイトのEZRで行う場合と見比べてみてください。
category == "A" と書いてあるところの意味が見えてきます。
ちなみに変数(1つ選択)のgripはgrip$gripの色のついた部分です。

スクリーンショット 2019-10-25 21.13.57


結果は以下のとおりです。
スクリーンショット 2019-10-25 19.36.44

どちらも0.5を超えているので正規分布であるという仮説は棄却されませんでした。
このあたりの解釈はハルさんのサイトをご参照ください。


7.1度に計算するsplit + map関数

shapiro.test(grip$grip[category == "A"])
shapiro.test(grip$grip[category == "B"])

上記のように1つずつ計算する方法もいいのですが群の数だけ繰り返します。プログラミングであるRは繰り返しに強いという特徴があります。


群ごとにデータを分割し、まとめて計算する方法として今回はsplit関数map関数を使います。


grip %>% 
  split(.$category) %>% 
  map(~shapiro.test(.$grip))

スクリーンショット 2019-10-26 22.42.55

まずgripのデータを
split関数を使ってA群とB群の2つのデータに分割し、map(~シャピロウィルク検定)でシャピロウィルク検定を繰り返します。

スクリーンショット 2019-10-26 23.01.43

EZRだと1つ1つ検定を繰り返す必要があります。
Rを活用すると1度に作業が終わるため、繰り返すことでのやり間違えの予防や時間の短縮にも繋がります。


8.等分散性を確認する

先程は正規性を調べましたが、今回は等分散性を調べます。
F検定と言いますがRではvar.test関数を使います。



Rで行うとこうなります。
var.test(目的変数 
~ グループ)

var.test(grip$grip ~ grip$category)

もしくはdata = を使えば$が要らなくなります。

var.test(grip ~ category, data = grip)
スクリーンショット 2019-10-27 5.57.05

p値 > 0.05だったので等分散性は棄却されませんでした。



9.t検定を行う

いままで正規分布かどうか、等分散性かどうかを確認しました。

スクリーンショット 2019-10-27 6.17.29

これでt検定が使えます。t検定はt.test関数を使います。
t検定は2種類の書き方があります。その違いはデータの形にあります。
ハルさんのサイトでEZRでは左の形しかできませんでしたがRならどちらも可能です
ちなみに左をlongデータ(縦に長い)、右をwideデータ(横に広い)といいます。
スクリーンショット 2019-10-27 21.34.00

スクリーンショット 2019-10-27 8.09.41

今回はlongデータなのでこのようになります。

t.test(grip$grip ~ grip$category, var = TRUE)

data = gripを使うとgrip$は外せます。どちらでも好きな方で大丈夫です。

t.test(grip ~ category, var = TRUE, data = grip)

スクリーンショット 2019-10-27 21.42.47
EZRと同じ結果になりました!


10.グラフの作成
EZRでは丁寧にグラフも作ってくれますがRでは自作する必要があります。
EZRでは平均と標準偏差の棒グラフを作成していました。
先程のgrip_summaryに平均と標準偏差を求めていたのでそれを使います。

棒グラフの作り方はここで紹介しています。


①最低限のグラフ(見た目は気にしない)

グラフを作る上で最低限必要な要素としては
棒グラフ:geom_bar(aes(x軸の指定、y軸の指定), stat = "identity")
エラーバー:geom_errobar(aes(x軸の指定, エラーバーの下端, エラーバーの上端))
y軸の名前が「平均」になるので「grip」に変更する

ggplot(data = grip_summary)+
  geom_bar(aes(x = category, y = 平均), stat = "identity") +
  geom_errorbar(aes(x = category, ymin = 平均 - 標準偏差, ymax = 平均 + 標準偏差)) + 
  labs(y = "grip") 
スクリーンショット 2019-10-27 22.59.56
ただこれでは見るに耐えません・・・



②見栄えを変更
次は以下を修正します。
棒グラフ:周りの線をblack、中の色をgray
エラーバー:幅を補足する(今回は0.1)

ggplot(data = grip_summary)+
  geom_bar(aes(x = category, y = 平均), color = "black", fill = "gray", stat = "identity") +
  geom_errorbar(aes(x = category, ymin = 平均 - 標準偏差, ymax = 平均 + 標準偏差), width = 0.1) + 
  labs(y = "grip")
スクリーンショット 2019-10-27 23.00.05
だいぶ見た目が良くなりました。



③EZRのグラフにできるだけ近づける
EZRのグラフに似せるためにもうひと工夫します。
背景を白にする(グラフのテーマをclassicに変える)
文字を大きくする(今回はsizeを15に変更)
棒グラフが浮いているように見えるのを修正する

ggplot(data = grip_summary)+
  geom_bar(aes(x = category, y = 平均), color = "black", fill = "gray", stat = "identity") +
  geom_errorbar(aes(x = category, ymin = 平均 - 標準偏差, ymax = 平均 + 標準偏差), width = 0.1) + 
  labs(y = "grip") +
  theme_classic(base_size = 15) +
  scale_y_continuous(expand = c(0,0), limits = c(0,50))
スクリーンショット 2019-10-27 23.00.12
これでEZRにだいぶ似ました。



11.まとめ

かなり長くなりましたが今回はt検定を紹介しました。

最初だったので1つ1つ説明しました。ボリュームが多すぎて慣れないところもあると思いますが、これから何度も出てくるものもありますので少しずつ慣れて貰えればと思います。


12.コードをまとめました
今回のコードを1つにまとめました。
パッケージはlibrary()を1度だけ行えばいいので最初に出しています。

#パッケージの読み込み
library(readxl)
library(tidyverse)

#データのダウンロード
url <- "https://haru-reha.com/wp-content/uploads/2018/03/demo-t-test.xlsx"
destfile = "data/demo-t-test.xlsx"

download.file(url, destfile)

#データの読み込み
grip <- read_excel("data/demo-t-test.xlsx", 
                   range = "B2:C62")
View(grip)  

#データの要約
grip_summary <- 
  grip %>% 
  group_by(category) %>% 
  summarize(平均 = mean(grip),
              標準偏差 = sd(grip),
              '0%' = quantile(grip, 0),
              '25%' = quantile(grip, 0.25),
              '50%' = quantile(grip, 0.5),
              '75%' = quantile(grip, 0.75),
              '100%' = quantile(grip, 1),
              n = n())
grip_summary

#正規性を調べる
#ヒストグラム
ggplot(data = grip) + 
  geom_histogram(aes(x = grip, fill = category), position = "dodge", bins = 5) 

#シャピロ・ウィルク検定
shapiro.test(grip$grip[category == "A"])
shapiro.test(grip$grip[category == "B"])

grip %>% 
  split(.$category) %>% 
  map(~shapiro.test(.$grip))


#等分散性を確認
var.test(grip ~ category, data = grip)

#t検定
t.test(grip$grip ~ grip$category, var = TRUE)

t.test(grip ~ category, var = TRUE, data = grip)

#グラフ化
ggplot(data = grip_summary)+
  geom_bar(aes(x = category, y = 平均), stat = "identity") +
  geom_errorbar(aes(x = category, ymin = 平均 - 標準偏差, ymax = 平均 + 標準偏差)) + 
  labs(y = "grip") 

ggplot(data = grip_summary)+
  geom_bar(aes(x = category, y = 平均), color = "black", fill = "gray", stat = "identity") +
  geom_errorbar(aes(x = category, ymin = 平均 - 標準偏差, ymax = 平均 + 標準偏差), width = 0.1) + 
  labs(y = "grip")

ggplot(data = grip_summary)+
  geom_bar(aes(x = category, y = 平均), color = "black", fill = "gray", stat = "identity") +
  geom_errorbar(aes(x = category, ymin = 平均 - 標準偏差, ymax = 平均 + 標準偏差), width = 0.1) + 
  labs(y = "grip") +
  theme_classic(base_size = 15) +
  scale_y_continuous(expand = c(0,0), limits = c(0,50))

                


↑このページのトップヘ