ひさびさに,共同研究でコサイナー解析 (cosinor analysis)を頼まれたので,ポイントをメモっておきます.コサイナー解析というのは,周期的に変化すると思われる時系列に,コサインの波形を当てはめてる分析法です.概日リズムの特徴付けに使われることがあります.Rでは,"cosinor"パッケージがあります.ただし,このパッケージの結果では位相が180°ずれることがあるので,結果の解釈には注意が必要です.ここでは,自作のRスクリプトを下に載せておきました.
周期回帰モデルの当てはめ
コサイナー解析では周期 を既知として,以下のモデルを仮定します.
ここで,は,MESOR (midline statistic of rhythm),は振幅,はacrophase (頂点位相)と呼ばれるパラメタです.は,ランダムな要因やその他の変動を表します.
観測されて時系列から,の2乗和が最小になるように,,,を推定します.そのために,
と変形します.ここで,
,
,
とおけば,
となります.
点の観測データがえられたとき,まず,,,を推定すると,
となります.ここで,
,
であることを忘れないでください.また,,,に,ハットと呼ばれる飾りがついているのは,これらが,真の,,ではなく,それらを推定した値だよという気持ちを表しています.
,,を推定したら,
と変換できます.この式だと,の定義から,と範囲が狭くなり,場合によって正しい が推定できません (180°ずれる).この問題を避けるために,実際の計算 (RやC言語など)では,atan2
を使えば良いと思います (下記のRスクリプト参照).
このモデルの検定は,周期の変動はないという帰無仮説を検証します.以下のRスクリプトでは,F検定の結果を計算しています.方法は,この論文
Cornelissen, G. (2014). Cosinor-based rhythmometry. Theoretical Biology and Medical Modelling, 11(1), 1-24.
に説明してあります.
Rスクリプト
パッケージに頼らないバージョンです.
# 周期 T <- 24 # テスト用の数値データの生成 time <- seq(0,24,1) mesor <- 0 amp <- 2 phase <- 0 eps <- rnorm(length(time)) y <- mesor+amp*cos(2*pi*time/T-phase)+eps ##################### # プロット par(mfrow=c(1,1),pty="m") plot(time,y,xlab="time",col=4,cex=1.2) ################################## # Cosinor解析 N <- length(y) x <- cos(2*pi*time/T) z <- sin(2*pi*time/T) # Y <- matrix(c(sum(y),sum(y*x),sum(y*z)), ncol=1) X <- matrix(c(N,sx<-sum(x),sz<-sum(z),sx,sum(x^2),sxz<-sum(x*z),sz,sxz,sum(z^2)),ncol=3) X.inv <- solve(X) A <- X.inv %*% Y # モデルパラメタの推定結果 mesor.est <- A[1,1] amp.est <- sqrt(A[2,1]^2+A[3,1]^2) phase.est <- atan2(A[3,1],A[2,1]) # 当てはめ結果のプロット curve(amp.est*cos(2*pi*x/T-phase.est)+mesor.est,xlim=c(min(time-12),max(time+12)),add=TRUE,col=2,lwd=2) ################################### y.bar <- mean(y) y.hat <- mesor.est+amp.est*cos(2*pi*time/T-phase.est) ### MSS <- sum((y.hat-y.bar)^2) RSS <- sum((y-y.hat)^2) ### sig2.est <- RSS/(N-3) F.stat <- (MSS/2)/sig2.est p.value <- 1-pf(F.stat,2,N-3) TXT <- sprintf("MESOR = %f\nA = %f\nphi = %f\np = %f\n",mesor.est,amp.est,phase.est,p.value) cat(TXT)
"cosinor"パッケージというのもあります.ただし,このパッケージは,の呪いが残っているので,位相が (180°)ずれた推定結果がでる場合があります.フィットの結果を見て,rrr
がマイナスのときは,acrophaseに足すか,引くか,自分でやってください.
# コサイナー解析(パッケージを使用) # install.packages("cosinor") require(cosinor) ### # モデル当てはめ cos.fit <- cosinor.lm(y~time(t), period = 24, data=data.frame(t=time,y=y))