diff --git a/docs/src/examples.md b/docs/src/examples.md index d70062e..be54c9f 100644 --- a/docs/src/examples.md +++ b/docs/src/examples.md @@ -7,6 +7,9 @@ rds = CSV.File(joinpath(dirname(pathof(Metida)), "..", "test", "csv", "1fptime. rds2 = CSV.File(joinpath(dirname(pathof(Metida)), "..", "test", "csv", "ftdf3.csv"); types = [String, Float64, Float64, String, String, String, String, String, Float64]) |> DataFrame + +devday = CSV.File(joinpath(dirname(pathof(Metida)), "..", "test", "csv", "devday.csv"); types = [Float64, String, String, String ]) |> DataFrame + nothing; # hide ``` @@ -197,3 +200,50 @@ MixedModels result: mm = fit(MixedModel, @formula(response ~ factor+ (0+r1|subject)), rds2, REML = true) println(mm) #hide ``` + +## Aumented covariance (Experimental) + +Covariance modificator `ACOV()` can be used as second repeated effect. In this case covariance calculated with existed matrix, +that was build at previous step. For example addition `ACOV(AR)` to `DIAG` structure is the same as `ARH` if same blocking factor used. + +```@example lmmexample + lmm1 = Metida.LMM(@formula(response ~ 1), rds2; + repeated = [Metida.VarEffect(Metida.@covstr(r1|subject), Metida.DIAG), Metida.VarEffect(Metida.@covstr(1|subject), Metida.ACOV(Metida.AR))] + ) + Metida.fit!(lmm1) +``` + +```@example lmmexample + lmm2 = Metida.LMM(@formula(response ~ 1), rds2; + repeated = [Metida.VarEffect(Metida.@covstr(r1|subject), Metida.ARH)] + ) + Metida.fit!(lmm2) +``` + +R-part of variance-covariance matrix: + +```@example lmmexample +Metida.rmatrix(lmm1, 1) +``` + +If nested blocking factor used - covariance modification applyed only within that blocks: + +```@example lmmexample + lmm = Metida.LMM(@formula(response ~ 1), rds2; + repeated = [Metida.VarEffect(Metida.@covstr(r1|subject), Metida.DIAG), Metida.VarEffect(Metida.@covstr(1|subject), Metida.ACOV(Metida.AR))] + ) +Metida.fit!(lmm) +Metida.rmatrix(lmm, 1) +``` + +For nested models covariance structure can be expanded as follows: +* the first layer describes unstructured the device-device covariance; +* the second layer adds the time covariance for each device + +```@example lmmexample +lmm = Metida.LMM(@formula(resp ~ 0 + device), devday; + repeated = [Metida.VarEffect(Metida.@covstr(device|subj&day), Metida.UN), + Metida.VarEffect(Metida.@covstr(1|subj&device), Metida.ACOV(Metida.AR))] + ) + Metida.fit!(lmm) +``` \ No newline at end of file diff --git a/src/rmat.jl b/src/rmat.jl index f0e22b9..f86d3d1 100644 --- a/src/rmat.jl +++ b/src/rmat.jl @@ -349,9 +349,9 @@ function rmat!(mx, θ, ::AbstractMatrix, ::ACOV_{AR_}, ::Int) ρ = θ[1] if s > 1 for n = 2:s - mxnn = mx[n, n] + mxnn = sqrt(mx[n, n]) @inbounds @simd for m = 1:n-1 - mxmm = mx[m, m] + mxmm = sqrt(mx[m, m]) mx[m, n] += mxnn * mxmm * ρ ^ (n - m) end end @@ -365,9 +365,9 @@ function rmat!(mx, θ, ::AbstractMatrix, ::ACOV_{CS_}, ::Int) ρ = θ[1] if s > 1 for n = 2:s - mxnn = mx[n, n] + mxnn = sqrt(mx[n, n]) @inbounds @simd for m = 1:n-1 - mxmm = mx[m, m] + mxmm = sqrt(mx[m, m]) mx[m, n] += mxnn * mxmm * ρ end end diff --git a/test/csv/devday.csv b/test/csv/devday.csv new file mode 100644 index 0000000..9b17f18 --- /dev/null +++ b/test/csv/devday.csv @@ -0,0 +1,201 @@ +resp,device,day,subj +8.72644141172539,A,d1,1 +5.042766927404885,A,d2,1 +4.186325590586714,B,d1,1 +1.5284483141734233,B,d2,1 +0.9795814766598748,C,d1,1 +-0.9859211795111515,C,d2,1 +1.815722019857775,D,d1,1 +0.6483360099159381,D,d2,1 +7.678877996324462,A,d1,2 +2.6894607393966203,A,d2,2 +1.604802444054944,B,d1,2 +0.06477952808780052,B,d2,2 +0.08761542039857528,C,d1,2 +-1.3153348196357393,C,d2,2 +-0.9458496052444734,D,d1,2 +-2.3047486276895612,D,d2,2 +5.450560693901975,A,d1,3 +9.686372619790028,A,d2,3 +1.718464421060092,B,d1,3 +0.030382263239601137,B,d2,3 +-2.4141035515735343,C,d1,3 +0.6145971257996419,C,d2,3 +-3.515779754752826,D,d1,3 +-0.7924377776322691,D,d2,3 +3.813544710443301,A,d1,4 +12.777701384288903,A,d2,4 +3.154188215710133,B,d1,4 +2.4545212975960635,B,d2,4 +2.284534141269639,C,d1,4 +3.4115586474605095,C,d2,4 +-0.7744416190640289,D,d1,4 +7.95734682057995,D,d2,4 +3.3770983614013477,A,d1,5 +8.61767085794332,A,d2,5 +0.12254119897458726,B,d1,5 +0.11468021929091354,B,d2,5 +-1.2647252830578548,C,d1,5 +-3.3506493037154055,C,d2,5 +-1.6918095598060048,D,d1,5 +1.3253048725047756,D,d2,5 +5.145425009462966,A,d1,6 +5.73725942229559,A,d2,6 +-2.223309642785237,B,d1,6 +0.48648011474864816,B,d2,6 +-2.2012177614506925,C,d1,6 +1.857075727529136,C,d2,6 +-0.8133054820871612,D,d1,6 +-1.7113560168975663,D,d2,6 +8.397112273554288,A,d1,7 +5.376131243152009,A,d2,7 +1.3669177848374323,B,d1,7 +0.9721548281418051,B,d2,7 +3.8985366050168295,C,d1,7 +5.0750678263487226,C,d2,7 +1.5763379519478005,D,d1,7 +-0.3861128068611285,D,d2,7 +9.648303006727525,A,d1,8 +3.710151996757312,A,d2,8 +5.972807663495972,B,d1,8 +4.350390974281194,B,d2,8 +6.258768605837868,C,d1,8 +3.2105071403214387,C,d2,8 +0.15393124061539032,D,d1,8 +-2.5547763361476363,D,d2,8 +-3.0677265537030856,A,d1,9 +4.359136440390644,A,d2,9 +2.907110623730842,B,d1,9 +4.125411410488164,B,d2,9 +1.9761189694982417,C,d1,9 +3.441883797936557,C,d2,9 +-3.0685326916867455,D,d1,9 +0.054118435162489154,D,d2,9 +13.422777347466306,A,d1,10 +11.210858574151388,A,d2,10 +2.567888661554812,B,d1,10 +2.0304319022284214,B,d2,10 +4.88611278655465,C,d1,10 +6.6320285634018035,C,d2,10 +3.9142760470343623,D,d1,10 +2.311911619953296,D,d2,10 +10.852130694348503,A,d1,11 +14.42127903982665,A,d2,11 +0.1469522649229611,B,d1,11 +0.6032038811808991,B,d2,11 +1.7384554039467177,C,d1,11 +3.7227138685731767,C,d2,11 +4.571523846566923,D,d1,11 +4.649026040495684,D,d2,11 +3.910138496014496,A,d1,12 +6.413750313180211,A,d2,12 +5.807001050879677,B,d1,12 +6.260160795303587,B,d2,12 +1.8520450445342187,C,d1,12 +2.5009282390307,C,d2,12 +1.125568283667134,D,d1,12 +0.8129924247764678,D,d2,12 +12.807794580205472,A,d1,13 +8.322436119924697,A,d2,13 +-0.643452270161581,B,d1,13 +0.12092707191439489,B,d2,13 +3.297069094909194,C,d1,13 +4.742854206617035,C,d2,13 +4.047117851822433,D,d1,13 +0.03296896782164138,D,d2,13 +16.7741439108485,A,d1,14 +12.760981727316295,A,d2,14 +3.025831544500329,B,d1,14 +0.7764413317042818,B,d2,14 +0.7283189557517783,C,d1,14 +-1.681301630849537,C,d2,14 +1.1249346588251992,D,d1,14 +1.6231214727388714,D,d2,14 +1.1246966748387255,A,d1,15 +1.2672197542452492,A,d2,15 +1.4941892508494075,B,d1,15 +1.512177146769281,B,d2,15 +-0.4192343747406144,C,d1,15 +0.5862372477457867,C,d2,15 +5.455303216158969,D,d1,15 +4.850268579460773,D,d2,15 +10.38511257681331,A,d1,16 +3.5594224801002063,A,d2,16 +2.017868297443292,B,d1,16 +3.3160949613203567,B,d2,16 +-1.0531480693202222,C,d1,16 +-0.20796996778768984,C,d2,16 +6.247290182493918,D,d1,16 +2.4417104552202438,D,d2,16 +4.80729810661313,A,d1,17 +3.2628217713572756,A,d2,17 +5.845990666877865,B,d1,17 +2.583367936379729,B,d2,17 +3.3169837345113145,C,d1,17 +-1.9964079746573784,C,d2,17 +4.39487372646855,D,d1,17 +4.157044282085577,D,d2,17 +10.240318518673588,A,d1,18 +14.724152656599722,A,d2,18 +4.865357847811297,B,d1,18 +4.071158435185416,B,d2,18 +-2.116276900225867,C,d1,18 +-3.867495508642045,C,d2,18 +2.870381121395314,D,d1,18 +4.708722201098421,D,d2,18 +4.8562563713220825,A,d1,19 +4.5760071217033005,A,d2,19 +1.6176851722177807,B,d1,19 +2.6617247815087386,B,d2,19 +-1.3799915893055932,C,d1,19 +0.9866728829505078,C,d2,19 +-2.124344897272937,D,d1,19 +-3.130651750605242,D,d2,19 +0.18496358374393562,A,d1,20 +0.9557850624985917,A,d2,20 +0.7288280847524664,B,d1,20 +-0.4653435413372957,B,d2,20 +-4.6925213895237645,C,d1,20 +-3.652115979512705,C,d2,20 +-2.6967213093392153,D,d1,20 +-4.970890111045517,D,d2,20 +18.882415907571957,A,d1,21 +9.129998873762691,A,d2,21 +1.2505737700650539,B,d1,21 +1.8671953191999,B,d2,21 +2.9582298279460426,C,d1,21 +3.2523729228338585,C,d2,21 +8.72277942030761,D,d1,21 +0.07794228444739426,D,d2,21 +5.591890694646271,A,d1,22 +-0.2507794772165646,A,d2,22 +1.5310835263928027,B,d1,22 +2.044698264019736,B,d2,22 +6.801136978998133,C,d1,22 +5.960395462799964,C,d2,22 +2.225244352202252,D,d1,22 +-1.7665234021467722,D,d2,22 +-1.644908989372592,A,d1,23 +4.138929775513601,A,d2,23 +0.5414403712038367,B,d1,23 +1.3474687738265696,B,d2,23 +-1.557993926205957,C,d1,23 +-0.04959539261802259,C,d2,23 +0.33090714708551583,D,d1,23 +7.644973558045834,D,d2,23 +4.372814545327468,A,d1,24 +2.4552865467212563,A,d2,24 +2.867106981327366,B,d1,24 +2.319283001308714,B,d2,24 +2.627484685332814,C,d1,24 +3.192937342625959,C,d2,24 +-3.362245762573469,D,d1,24 +-5.449220541955391,D,d2,24 +7.1001679809270275,A,d1,25 +5.5622476539561605,A,d2,25 +1.1671137090721442,B,d1,25 +3.302995065925057,B,d2,25 +2.1447737535208518,C,d1,25 +2.2562198630023285,C,d2,25 +0.8165695676079928,D,d1,25 +-3.619761855447412,D,d2,25 diff --git a/test/test.jl b/test/test.jl index 8b8139b..ff51069 100644 --- a/test/test.jl +++ b/test/test.jl @@ -782,6 +782,54 @@ end @test_nowarn Metida.fit!(lmm; varlinkf = :identity) end +@testset " Model: Augmented covariance " begin + lmm1 = Metida.LMM(@formula(response ~ 1), ftdf3; + repeated = [Metida.VarEffect(Metida.@covstr(r1|subject), Metida.DIAG), Metida.VarEffect(Metida.@covstr(1|subject), Metida.ACOV(Metida.AR))] + ) + Metida.fit!(lmm1) + + lmm2 = Metida.LMM(@formula(response ~ 1), ftdf3; + repeated = [Metida.VarEffect(Metida.@covstr(r1|subject), Metida.ARH)] + ) + Metida.fit!(lmm2) + @test Metida.m2logreml(lmm1) ≈ Metida.m2logreml(lmm2) + + + lmm1 = Metida.LMM(@formula(response ~ 1), ftdf3; + repeated = [Metida.VarEffect(Metida.@covstr(r1|subject), Metida.DIAG), Metida.VarEffect(Metida.@covstr(1|subject), Metida.ACOV(Metida.CS))] + ) + Metida.fit!(lmm1) + + lmm2 = Metida.LMM(@formula(response ~ 1), ftdf3; + repeated = [Metida.VarEffect(Metida.@covstr(r1|subject), Metida.CSH)] + ) + Metida.fit!(lmm2) + @test Metida.m2logreml(lmm1) ≈ Metida.m2logreml(lmm2) + + lmm = Metida.LMM(@formula(response ~ 1), ftdf3; + repeated = [Metida.VarEffect(Metida.@covstr(r1|subject), Metida.DIAG), Metida.VarEffect(Metida.@covstr(1|subject&r2), Metida.ACOV(Metida.AR))] + ) + Metida.fit!(lmm) + @test Metida.m2logreml(lmm) ≈ 800.7606945922405 atol=1E-6 + + + lmm1 = Metida.LMM(@formula(resp ~ 0 + device), devday; + repeated = [Metida.VarEffect(Metida.@covstr(device|subj&day), Metida.UN), + Metida.VarEffect(Metida.@covstr(1|subj&device), Metida.ACOV(Metida.CS))] + ) + Metida.fit!(lmm1) + + lmm2 = Metida.LMM(@formula(resp ~ 0 + device), devday; + repeated = [Metida.VarEffect(Metida.@covstr(device|subj&day), Metida.UN), + Metida.VarEffect(Metida.@covstr(1|subj&device), Metida.ACOV(Metida.AR))] + ) + Metida.fit!(lmm2) + @test Metida.m2logreml(lmm1) ≈ Metida.m2logreml(lmm2) + +end + + + @testset " Random " begin lmm = Metida.LMM(@formula(response ~ 1 + factor*time), ftdf2; random = Metida.VarEffect(Metida.@covstr(factor|subject&factor), Metida.DIAG), diff --git a/test/testdata.jl b/test/testdata.jl index 4d6077d..ba1d9d3 100644 --- a/test/testdata.jl +++ b/test/testdata.jl @@ -17,6 +17,7 @@ ftdf3 = CSV.File(path*"/csv/ftdf3.csv"; types = spatdf = CSV.File(path*"/csv/spatialdata.csv"; types = [Int, Int, String, Float64, Float64, Float64, Float64, Float64]) |> DataFrame +devday = CSV.File(path*"/csv/devday.csv"; types = [ Float64, String, String, String]) |> DataFrame dfrdsfda = CSV.File(joinpath(path, "csv", "berds", "rds1.csv"), types = Dict(:PK => Float64, :subject => String, :period => String, :sequence => String, :treatment => String )) |> DataFrame dropmissing!(dfrdsfda)