3 ノンパラ対応あり
#basic #ノンパラ
今回は、反復測定のデータで同一個体を線で結ぶグラフを描きます。
その際、dotと線を群ごとに色分けをします。
ただ、このやり方だと、いわゆる二元配置のデータということになりますが、ノンパラ版の二元配置以上の分散分析に変わる検定は一般的には知られていませんので、ここでは繰り返しのある一元配置分散分析の状況で用いるノンパラ検定(フリードマン検定)を、統計としては行います。
https://scrapbox.io/files/63879913b31230001d97a290.png
こんなグラフになります。僕は、こういうグラフを自由自在に無料で描けるようになりたいと思い、Rを始めました。
scriptは以下です。
code:r
# ---------- preparation in advanca 事前準備--------------------------------------------------
# Install packages if not installed 必要なパッケージが無けれな自動でインストール-----
if(!require("tidyverse")) install.packages("tidyverse")
if(!require("dplyr")) install.packages("dplyr")
if(!require("ggplot2")) install.packages("ggplot2")
if(!require("exactRankTests")) install.packages("exactRankTests")
# clear R's brain 一度参照したリストもしくは変数を次の作業で消す-----
rm(list = ls())
# Load libraries 必要なパッケージの読み込み-----
library(tidyverse)
library(dplyr) #データ整形に使う
library(ggplot2)
library(exactRankTests) #needed fo Exact Rank Tests
# Data input 今後以下のパスからデータを自動で読み込みする場合-----
library(readr)
CanRsample <- read.csv(file.choose()) #Run and choose CanRsample2021.csv
#ここを実行(Run)するとfile選択画面になるので、どのfileを読み込んだか上に記録!
#横長データをtidyデータに変換したものも予め作っておく(多重比較や作図に便利)
CanRsample_tidy <- gather(CanRsample, key = "Season", value = "aveTemp", aveTemp_SpAut, aveTemp_summer, aveTemp_winter)
#keyは新しく作る列名(カテゴリカル変数名)、valueは値の新しい列名、その後に続くのが縦長に並べ替えたい列名
# # ----------prep done 準備だん------------------------------------------------------------
# 【3】box plots within 箱ひげ図 個体内----------------------------
#春秋vs夏vs冬で比較する例
oneway_within <-matrix(c(CanRsample$aveTemp_SpAut, CanRsample$aveTemp_summer, CanRsample$aveTemp_winter), ncol = 3)
#比較対象の列だけ抽出、「ncol = 反復数」を指定(フリードマンへの受け渡し用)
friedman.test(oneway_within)
pairwise.wilcox.test(CanRsample_tidy$aveTemp, CanRsample_tidy$Season, paired=T, correct=F, exact=F, p.adj="holm")
#2条件で比較したい時
wilcox.test(CanRsample$aveTemp_SpAut, CanRsample$aveTemp_summer, paired=T, correct=F, exact=F, p.adj="holm") 
wilcox.exact(CanRsample$aveTemp_SpAut, CanRsample$aveTemp_summer, paired=T, correct=F, exact=F, p.adj="holm")
#Fig_boxplotCol <- #線とdotに色付きver
ggplot(CanRsample_tidy, aes(x = Season, y = aveTemp)) + #tidyに直した新しいデータフレームのオブジェクトを使用
scale_x_discrete(limit=c('aveTemp_SpAut', 'aveTemp_summer', 'aveTemp_winter')) +
#X軸に表示したい順番の指定、不要なら消す
geom_boxplot(size = 1.0, width = 0.3) + #sizeは線の太さ、widthはboxの太さ
geom_line(aes(group = ID_town, colour = place), alpha = 0.5) +
#geom_jitter(shape = 21, size = 4, aes(fill = place), width = 0.2, alpha = 0.7) +
geom_point(size = 4, aes(colour = place), alpha = 0.7) + #alphaはdotの透明度
#データセットと使用する変数の指定、colour:群ごとにdotの色を変える
scale_fill_manual(values = c (Sendai = "deepskyblue3", Tokyo = "gray1", Kagoshima = "orange" )) +
#dotの色をRで自動指定したい場合上記関数を消す
scale_color_manual(values = c (Sendai = "deepskyblue3", Tokyo = "gray1", Kagoshima = "orange" )) +
#個体を繋ぐ線の色をRで自動指定したい場合上記関数を消す
xlab("季節") + #X軸のラベル
ylab("季節ごとの平均気温") + #Y軸のラベル
#ylim(max, min) + #Y軸の(最大値, 最小値)を指定する場合は記入して先頭の#を消す
#coord_flip() + #XとYの入れ替えに使う
ggtitle("【3】box plots within 箱ひげ図 個体内") +
theme_classic(base_size = 18, base_family = "HiraKakuProN-W3") # white backgrond グラフの背景を白に
#theme(legend.position = "none") #凡例を消したい時は#を消して上のcodeの最後に+を足して有効にする
【データ整形】
今回は、フリードマン検定の後検定での多重比較を行うために、横長データ(ワイド型)を縦長データ(ロング型)に変える必要があります。フリードマン検定のデータ指定の方法と、多重比較に使う pairwise.wilcox.test() のデータ指定の方法が異なるのです。また、グラフを描く際も、ロング型である必要があります。
このデータ整形で活躍するのが、tidyverse というパッケージです。データ整形で大変重宝されています。
いつものようにデータファイルのcsvを読み込むscriptの後に、今回は以下のように書いてあります。
code:r
CanRsample_tidy <- gather(CanRsample, key = "Season", value = "aveTemp", aveTemp_SpAut, aveTemp_summer, aveTemp_winter)
#keyは新しく作る列名(カテゴリカル変数名)、valueは値の新しい列名、その後に続くのが縦長に並べ替えたい列名
gather() という関数を使っています。
この関数の使い方とデータの並び替えは、以下のサイトなどでイメージを持ってもらうと分かりやすいと思います。
https://antnestin.hatenablog.com/entry/2021/12/25/160822
ロング型のデータでは同一個体/被験者のデータが複数の行に別れることになります。で、色んな関数で「IDが同一なら同一個体である」みたいな指定をすることで、グラフに線を引いたりすることが可能になります。
【統計:Friedman's testとWilcoxon signed rank test】
フリードマン検定は、データの指定の仕方だけ、若干面倒です。最初に使用するデータマトリックスを作ってあげないといけません。スクリプト中では、
oneway_within <-matrix(c(CanRsample$aveTemp_SpAut, CanRsample$aveTemp_summer, CanRsample$aveTemp_winter), ncol = 3)
ここでは、matrixという関数を使って、ワイド型データのCanRsampleの中から、横並びで記載している3つの季節のデータを抽出しています。最後に、ncol = 3 で、3回の反復であることを指定しています。このようにまとめたデータを、oneway_within というオブジェクトにしています。
ここまでくると、フリードマン検定は簡単で、friedman.test(使用するデータのオブジェクト)というカタチで指定して実行すればOKです。今回の検定の結果は有意になります。
多重比較では、ペアワイズな検定の関数を用います。
pairwise.wilcox.test(使用するロング型データ$従属変数, 使用するロング型データ$条件となる独立変数, paired=T, correct=F, exact=F, p.adj="holm")
のように書きます。ここで使うデータは、先ほど作っておいたロング型データの CanRsample_tidy です。
対応のある2条件間の比較のノンパラは、ウィルコクソンの符号付き順位検定(Wilcoxon signed rank test)です。符号付き順位"和"検定と、和をつけている訳も見受けられますが、これは間違いじゃないかなと僕は思ってます。対応ない検定の名前と並べると
ウィルコクソンの順位和検定(Wilcoxon rank sum test):対応のない2群間のノンパラ検定、U検定と同じ結果が出る(2 ノンパラ対応なし群間差参照)
ウィルコクソンの符号付き順位検定(Wilcoxon signed rank test):対応のある2条件間の比較の検定
というように、英語の名称で、sum(和)の有る/無し に違いがあります。
統計のスクリプトの最後に、2条件間でウィルコクソンの符号付き順位検定を実行するスクリプトの例も書いてあります。
2 ノンパラ対応なし群間差でやった群間の差を見るノンパラ検定と異なり、
Friedman's testとWilcoxon signed rank testは、等分散性の問題を気にしなくて良いので、使い勝手が良いと思っています。ノンパラですから、正規性を仮定しなくて良いので、事前に分布を見る(これ自体に検定を繰り返すことで起るたType 1 error の危険がある)必要もなく、統計の面から見れば、安定した実験デザインになると言えます。なので、最近僕は、なるべく反復測定の実験デザインにして、個体内での変化として実験の効果を検討できるように計画をすることが多いです。
【グラフの描画】
用いるデータ形式
これまでのページで行ってきたグラフ描画とかなり違いので、それらとの相違点だけ触れていきます。
同一個体のデータに線を引く場合は、用いるデータはロング型になるので、ここでは、tidyversのgather()で作った、CanRsample_tidyをデータとして指定します。
ボックスプロット
ノンパラはボックスプロットで描くことにしているので、
geom_boxplot()
を使っています。
同一個体のデータに線を引く
geom_line()という関数を使います。知ってしまえば大したことはないのですが、、、Rを勉強し始めた初期に結構書き方に手間取った印象です。ポイントは以下のように、
geom_line(aes(group = ID_town, colour = place), alpha = 0.5)
geom_line(aes(group = 個体IDなど, colour = 群の名前の独立変数), )のように指定することです。
ドットの描き方
線とdotを接続させるためには、geom_jitterを使うと見辛くなるので(描画自体は出力される)、geome_pointを使いましょう。
【色分けが不要な場合】
条件間の違い(横軸に書かれた独立変数の違い)さえ分かれば良いので「色などいらん」という方向けに、モノクロで描く際のスクリプトも以下に置いておきます。
https://scrapbox.io/files/63879920ce8b55001f03109d.png
code:r
#Fig_boxplot_withinMono <- #線とdotもモノクロver
ggplot(CanRsample_tidy, aes(x = Season, y = aveTemp)) +
geom_boxplot(size = 1.0, width = 0.3) + #sizeは線の太さ、widthはboxの太さ
geom_line(aes(group = ID_town), color = "grey", alpha = 0.5) +
#geom_jitter(shape = 21, size = 4, color = "black", width = 0.2, alpha = 0.7) +
geom_point(size = 4, color = "grey", alpha = 0.8) + #alphaはdotの透明度
#データセットと使用する変数の指定、colour:群ごとにdotの色を変える
#scale_color_manual(values = c (グループ名1 = "色1", グループ2 = "色2")) +
#色を自由に指定したい場合、上記先頭の#を取って色を指定
xlab("季節") + #X軸のラベル
ylab("季節ごとの平均気温") + #Y軸のラベル
#ylim(max, min) + #Y軸の(最大値, 最小値)を指定する場合は記入して先頭の#を消す
ggtitle("【3_2】Fig_boxplot_withinMono 線とdotもモノクロver") +
#coord_flip() + #XとYの入れ替えに使う
theme_classic(base_size = 18, base_family = "HiraKakuProN-W3") # white backgrond グラフの背景を白に
#theme(legend.position = "none") #凡例を消したい時は#を消して上のcodeの最後に+を足して有効にする