ベクトル自己回帰(VAR)モデルは基本的にパラメータの定常性(時間によって変化しないこと)を仮定している。
心理変数間の関係は時間に対して一定?心理的介入の前後では関係が変わるのでは?
時間経過にともなってパラメータ(偏相関係数など)が変化していくネットワークを時変(time-varying)ネットワークモデルと呼ぶ(Haslbeck J. M. B. et al., 2022)
平均ベクトル\(\mu_{t}\)や偏相関行列\(\Omega_{t}\)のように,パラメータに時間tの添字がつく。
ネットワークのパラメータの変化には連続的変化(左)と離散的変化(右,状態間でジャンプ有り)がある
連続か離散かによって解析が変わるので,理論的・実証的(先行研究)にどちらが適切か検討する
時系列上で窓を移動をさせていき,その窓ごとに局所モデルを多数推定する方法
固定窓と異なり,全てのデータポイントを利用するが特定の時点に重みをつけて推定(カーネル重み付け法,詳細は Haslbeck et al. (2020) )
移動窓アプローチでは,カーネル関数の幅(帯域幅)が重要になる
帯域幅が広いと多くのデータポイントを使うので,推定は安定するが時間変化の感度が下がる(オレンジ)。狭いと逆(緑)。
Journal of Open Psychology Dataに掲載された Kossakowski et al. (2017) のデータを用いる。
Kossakowski et al. (2017) は,1名のうつ病患者に239日間さまざまな症状を収集(1日10回で合計1478回答)
データはOSF(https://osf.io/j4fg8/)で配布されているので,ESMdata.zipをダウンロードして展開する。
同じデータがmgm(Haslbeck & Waldorp, 2020)パッケージに入っているが(symptom_data),実際の解析に近づけるためにcsvファイルから読み込む。
データの前処理にtidyverse(Wickham et al., 2019)を用い,日付や時間の情報の処理にlubridate(Grolemund & Wickham, 2011)を用いる
時変自己相関モデルにmgm(Haslbeck & Waldorp, 2020)を用い,可視化にqgraph(Epskamp et al., 2012)を用いる
mgmの使用法は,Haslbeckのブログ(Haslbeck, 2020)が参考になる
data <- read_csv("ESMdata/ESMdata.csv") |>
mutate(datetime = dmy_hms(paste(date, resptime_e)))
data$time_norm <- as.numeric(data$datetime-data$datetime[1])/as.numeric((data$datetime-data$datetime[1])[nrow(data)])
head(data)
# A tibble: 6 × 88
...1 date phase concentrat dayno beepno beeptime resptime_s resptime_e
<dbl> <chr> <dbl> <dbl> <dbl> <dbl> <time> <time> <time>
1 1 13/08/12 1 150 226 1 08:58 08:58:56 09:00:15
2 2 14/08/12 1 150 227 5 14:32 14:32:09 14:33:25
3 3 14/08/12 1 150 227 6 16:17 16:17:13 16:23:16
4 4 14/08/12 1 150 227 8 18:04 18:04:10 18:06:29
5 5 14/08/12 1 150 227 9 20:57 20:58:23 21:00:18
6 6 14/08/12 1 150 227 10 21:54 21:54:15 21:56:05
# ℹ 79 more variables: resp_abort <dbl>, mood_relaxed <dbl>, mood_down <dbl>,
# mood_irritat <dbl>, mood_satisfi <dbl>, mood_lonely <dbl>,
# mood_anxious <dbl>, mood_enthus <dbl>, mood_suspic <dbl>,
# mood_cheerf <dbl>, mood_guilty <dbl>, mood_doubt <dbl>, mood_strong <dbl>,
# pat_restl <dbl>, pat_agitate <dbl>, pat_worry <dbl>, pat_concent <dbl>,
# se_selflike <dbl>, se_ashamed <dbl>, se_selfdoub <dbl>, se_handle <dbl>,
# soc_who1 <dbl>, soc_enjoy_alone <dbl>, soc_prefcomp <dbl>, …
select()で使う変数を選択(気分12変数,時間関連5変数)
欠測があるので(5つの測定),filter()とcomplete.cases()で完全ケースに絞る
カーネル重み付き法では帯域幅の設定が重要(広いと推定は安定するが時間変化の感度が下がる)
bwSelect()でクロスバリデーションによって最も予測のエラーが小さい帯域幅を探索できる
set.seed(123)
bwSeq <- seq(0.01, 1, length = 10)
bw_object <- bwSelect(data = data_complete[,1:12],
type = rep("g", 12),
level = rep(1, 12),
bwSeq = bwSeq,
bwFolds = 1,
bwFoldsize = 10,
modeltype = "mvar",
lags = 1,
timepoints = data_complete$time_norm,
beepvar = data_complete$beepno,
dayvar = data_complete$dayno,
pbar = FALSE)
bandwidth <- bwSeq[which.min(bw_object$meanError)]
bandwidth
[1] 0.45
帯域幅が決まったので(0.45),tvmvar()で時変混合ベクトル自己回帰モデルで推定を行う
bwSelect()と同じ引数は省略。lambdaSelは正則化(今回はクロスバリデーション”CV”),estpointsは時間の分割(今回は20分割した),bandwidthにbwSelect()で決めた帯域幅を指定する。
node_labels <- c("Relaxed","Down","Irritat","Satisfi","Lonely","Anxious","Enthus","Suspic","Cheer","Guilty","Doubt","Strong")
par(mfrow=c(1,3))
for(tp in c(1,10,20)) {
qgraph(t(result_tvmvar$wadj[, , 1, tp]),
layout = "circle",
edge.color = t(result_tvmvar$edgecolor[, , 1, tp]),
labels = node_labels,
mar = rep(5, 4),
vsize=14, esize=15, asize=13,maximum = .5,
pie = pred_tvmvar$tverrors[[tp]][, 3],
title = paste0("Estimation point = ", tp), title.cex=1.2)
}
tibble(time = 1:20,
Doubt_Satisfi = result_tvmvar$wadj[4,11,1,],
Down_Lonely = result_tvmvar$wadj[5,2,1,],
Strong_Satisfi = result_tvmvar$wadj[4,12,1,]) |>
pivot_longer(cols=-time,
names_to = "variables",
values_to = "score") |>
mutate(variables = as.factor(variables)) |>
ggplot(aes(x=time,y=score, color=variables)) +
geom_line() +
geom_point()+
labs(x = "時間", y = "偏相関係数",color="変数") +
theme(text = element_text(family = "HiraKakuProN-W3"))
phase <- NULL
split_20 <- seq(0, 1, length = 20)
for (i in 1:length(split_20)) {
min_index <- which.min(abs(data_complete$time_norm - split_20[i]))
phase[i] <- data_complete$phase[min_index]
}
phase <- (phase/5)*0.16
tibble(time = 1:20,
Doubt_Satisfi = result_tvmvar$wadj[4,11,1,],
Down_Lonely = result_tvmvar$wadj[5,2,1,],
Strong_Satisfi = result_tvmvar$wadj[4,12,1,],
Phase = phase) |>
pivot_longer(cols=-time,
names_to = "variables",
values_to = "score") |>
mutate(variables = as.factor(variables)) |>
ggplot(aes(x=time,y=score, color=variables)) +
geom_line() +
geom_point()+
labs(x = "時間", y = "偏相関係数",color="変数") +
theme(text = element_text(family = "HiraKakuProN-W3"))