【初心者向け】経時データ・反復測定データをグラフ化して統計的に比較する方法!

  • URLをコピーしました!

こんにちは。ほしのはやしです。
Intervention群とControl群にわけて薬剤を投与したあとの各時点での比較をしたい場合、R studioでどのように解析を行うのか、できる限りわかりやすく解説していきたいと思います!

目次

今回扱う経時データのグラフ

まずはどのようなグラフを想定しているか共有していきます。

実験系でよく見るパターンのグラフです。
A, B, Control群でDay 28時点での差を見るなら、その時点をピックアップしてANOVAなりすればよいのですが、どの時点から差が出ているのか全ての時点で比較したいですよね!

本ページではその方法について具体的に解説していきます!

星柴くん

ネットで調べてみても意外と取り扱ってるサイトないのだ

今回扱うのは個体差がほぼないような系(細胞実験・動物実験系など)を想定しています。
臨床研究などで個体差の影響が大きいような場合には、線形混合モデル(Linear Mixed-Effects Models)を使用する必要がありますのでご注意ください。

Rでの解析方法

時系列データをlong形式:長形式にする

多くの場合、以下のようにエクセルにデータを入れていると思います。

データ名:datasheet

SubjectInterventionDay0Day3Day7Day10
1A180170160150
2B160120110115
3Control165155160170
4A170160150140
5B175155135120
6Control185190160180

これを以下のように解析に適した形に変更する必要があります。
この形のことをlong形式と呼びます。

SubjectInterventionDayBloodPressure
1ADay0180
1ADay3170
1ADay7160
1ADay10150
1ADay14140
1ADay17120

このように変更するためのRスクリプトは以下になります。

library(tidyverse)

# データをlong形式に変換
long_data <- datasheet %>% pivot_longer(cols = starts_with(“Day”), names_to = “Day”, values_to = “BloodPressure”)

【pivot_longer関数について
cols = starts_with(“Day”): “Day” で始まる列をすべて変換することを意味します。もしHour0, Hour1などの列名なら”Day”を”Hour”にしてください。
names_to = “Day”: 変換後の列名を指定します。名前をTimeしたければ”Day”を”Time”にしてください。
values_to = “BloodPressure”: 実際に格納されている数値の列名を設定します。今回は血圧の数値が入っているので”BloodPressure”と名付けました。腫瘍量なら”TumorVolume”などにしてください。

これらの名前を変更した場合は、後半のスクリプトも忘れずに名前を変更してください。

下記のようにDay列を数値だけをピックアップしたい場合は、以下のスクリプトを続けます。

データ名:long_data

SubjectInterventionDayBloodPressure
1A0180
1A3170
1A7160
1A10150
1A14140
1A17120

# 上記で作成したDay列から数値だけを取り出し、数値型に変換
long_data$Day <- as.numeric(gsub(“Day”, “”, long_data$Day))

平均値とSEMの計算をして新しいデータシートを作る

summary_data <- long_data %>%
group_by(Intervention, Day) %>%
summarise(mean_bp = mean(BloodPressure),
sem_bp = sd(BloodPressure) / sqrt(n()))

平均値とSDにしたい場合は以下のスクリプトを使用。

summary_data <- long_data %>%
group_by(Intervention, Day) %>%
summarise(mean_bp = mean(BloodPressure),
sd_bp = sd(BloodPressure))

エクセルに平均値のデータを出力したい場合は、以下になります。

library(openxlsx)
write.xlsx(summary_data, file = “test.xlsx”)

折れ線時系列グラフを作成する

パッケージggplot2を用いて、グラフを描きます。

library(ggplot2)

ggplot(summary_data, aes(x = Day, y = mean_bp, group = Intervention, color = Intervention)) +
geom_line(linewidth = 1) +
geom_point(size = 3) +
geom_errorbar(aes(ymin = mean_bp – sem_bp, ymax = mean_bp + sem_bp), size = 1, width = 0.2) +
labs(title = “Blood Pressure Over Time by Intervention Group”,
x = “Day”,
y = “Blood Pressure (Mean ± SEM)”) +
theme(axis.line = element_line(color = “black”, linewidth = 0.3, linetype = “solid”),
axis.text = element_text(color = “black”, size = 12),
axis.title = element_text(size = 14),
panel.background = element_blank(),
axis.ticks.length = unit(-2, “mm”),
axis.ticks = element_line(color = “black”, linewidth = 0.3)) +
scale_x_continuous(breaks = unique(long_data$Day))

もしMeanとSDで描画したい場合は、上記のsem_bpをsd_bpに変更してください!

統計解析

全ての群、全てのタイミングで正規性がある(あると考えられるような実験系の)場合は、下記のようにANOVAを用いて全てのタイミングで比較して多重性を補正します。

# 各時点ごとにANOVAと事後検定を実施
anova_results <- list()
posthoc_results <- list()

for (day in unique(long_data$Day)) {
subset_data <- long_data %>% filter(Day == day)
model <- aov(BloodPressure ~ Intervention, data = subset_data)
anova_results[[as.character(day)]] <- summary(model)
posthoc_results[[as.character(day)]] <- TukeyHSD(model)
}

# ANOVAの結果を表示
anova_results

# 事後検定の結果を表示
posthoc_results

抜粋した結果ですが、左上がDay 3, Day 7で補正されたp値が右側になります。

この方法の場合は各時点で繰り返し検定することの多重性が考慮されていないので、p値には注意をする必要があります。特にP値が0.05に近い場合は、Bonferroni法などでp値をさらに調整する必要があります。

正規性がない場合は以下の方法で計算します。今回は多重性の補正にDunn.testを用いています。

library(dunn.test)

# Day毎のKruskal-Wallis検定
kruskal_result <- long_data %>% group_by(Day) %>%
summarise(p_value = kruskal.test(BloodPressure ~ Intervention)$p.value)

# 有意な結果を持つDayを抽出
significant_days <- kruskal_result %>% filter(p_value < 0.05) %>% pull(Day)

# 各有意なDayについてDunnの手順による多重比較を実行
dunn_results <- lapply(significant_days, function(day) { dunn.test::dunn.test(long_data$BloodPressure[long_data$Day == day], long_data$Intervention[long_data$Day == day], method = “bonferroni”) })

# 結果を表示
names(dunn_results) <- paste(“Day”, significant_days)
dunn_results

Day毎に補正されたP値が表示されます。

星柴くん

実験系の場合は厳密性はあまり重視されず、ANOVAが使用されていることがほとんどなのだ。。。

まとめ

経時データをグラフ化および各時点毎を統計評価する方法について解説しました!
少しでもお役に立てれば幸いです!!

  • URLをコピーしました!

この記事を書いた人

柴犬をこよなく愛する読書家。
街歩きとお菓子作りを趣味にしています。
研究や論文に役立つ情報をわかりやすくお伝えします。

コメント

コメントする

目次