├── .Rbuildignore ├── .gitignore ├── .travis.yml ├── DESCRIPTION ├── NAMESPACE ├── NEWS.md ├── R ├── anova_contrasts.R ├── contest.R ├── contrast_utils.R ├── data_documentation.R ├── drop1.R ├── estimability.R ├── legacy.R ├── lmer.R ├── lmerTest.R ├── lmer_anova.R ├── lmer_summary.R ├── ls_means.R ├── ranova.R ├── step.R ├── terms_utils.R └── utils.R ├── README.md ├── data ├── TVbo.rda ├── carrots.rda └── ham.rda ├── inst ├── CITATION └── testdata │ ├── legacy_fits.RData │ ├── potdata.RData │ └── test_paper_objects.RData ├── man ├── TVbo.Rd ├── anova.lmerModLmerTest.Rd ├── as.data.frame.ls_means.Rd ├── as_lmerModLmerTest.Rd ├── carrots.Rd ├── containment.Rd ├── contest.Rd ├── contest.lmerModLmerTest.Rd ├── contest1D.lmerModLmerTest.Rd ├── contestMD.lmerModLmerTest.Rd ├── devfun_vp.Rd ├── doolittle.Rd ├── drop1.lmerModLmerTest.Rd ├── ensure_full_rank.Rd ├── get_Fstat_ddf.Rd ├── get_contrasts_type1.Rd ├── get_contrasts_type3.Rd ├── get_covbeta.Rd ├── get_model.Rd ├── get_model_matrix.Rd ├── get_rdX.Rd ├── ham.Rd ├── is_estimable.Rd ├── legacy.Rd ├── lmer.Rd ├── lmerModLmerTest-class.Rd ├── lmerTest-package.Rd ├── ls_means.Rd ├── ls_means.lmerModLmerTest.Rd ├── merModLmerTest-class.Rd ├── nullspace.Rd ├── plot.ls_means.Rd ├── plot.step_list.Rd ├── qform.Rd ├── ranova.Rd ├── rbindall.Rd ├── rm_complete_terms.Rd ├── show_tests.Rd ├── show_tests.anova.Rd ├── show_tests.ls_means.Rd ├── single_anova.Rd ├── step.Rd ├── step.lmerModLmerTest.Rd ├── summary.lmerModLmerTest.Rd └── term_contain.Rd ├── misc ├── copyright_header.txt └── modify_copyright_header.R ├── pkg_notes ├── Satterthwaite_for_LMMs.Rmd ├── Satterthwaite_for_LMMs.html ├── Satterthwaite_for_LMMs.md ├── Satterthwaite_for_LMMs.pdf ├── implementation.Rmd ├── implementation.html ├── implementation_notes.Rmd ├── implementation_notes.html ├── new_lmerTest.Rmd ├── new_lmerTest.html ├── new_lmerTest.pdf └── view_html.md └── tests ├── test_a_utils.R ├── test_anova.R ├── test_compare_sas.R ├── test_contest1D.R ├── test_contestMD.R ├── test_contrast_utils.R ├── test_drop1.R ├── test_legacy.R ├── test_lmer.R ├── test_lmerTest_paper.R ├── test_ls_means.R ├── test_ranova_step.R ├── test_summary.R ├── test_zerovar.R └── zlmerTest_zeroDenom.R /.Rbuildignore: -------------------------------------------------------------------------------- 1 | ^.*\.Rproj$ 2 | ^\.Rproj\.user$ 3 | ^\.gitignore 4 | ^\.git$ 5 | .*~$ 6 | README.md 7 | NEWS.html 8 | ^build$ 9 | ^revdep$ 10 | ^revdep_archive$ 11 | ^pkg_notes$ 12 | ^misc$ 13 | TODO.md 14 | .Rhistory 15 | ^.*\.Rproj$ 16 | ^\.travis.yml$ 17 | 18 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | .Rproj.user 2 | .Rhistory 3 | .RData 4 | .Ruserdata 5 | lmerTestR.Rproj 6 | # Ignore all files ending with a 'tilde' (autogenerated by some 7 | # programs, e.g. emacs): 8 | *~ 9 | revdep 10 | revdep_archive 11 | -------------------------------------------------------------------------------- /.travis.yml: -------------------------------------------------------------------------------- 1 | # .travis.yml for Travis CI 2 | # https://docs.travis-ci.com/user/languages/r 3 | # https://github.com/craigcitro/r-travis/wiki/Porting-to-native-R-support-in-Travis 4 | 5 | language: r 6 | r: 7 | - oldrel 8 | - release 9 | - devel 10 | cache: packages 11 | # helpful when preparing your package for submission to CRAN 12 | warnings_are_errors: true 13 | # No need for sudo as R is natively supported now. 14 | sudo: false 15 | # r_build_args: --no-build-vignettes 16 | # r_check_args: --as-cran --no-build-vignettes 17 | 18 | # chicago.bst not needed for the vignette bibliographi: 19 | # before_install: 20 | # - tlmgr install chicago 21 | 22 | # need to add nloptr this way to make it build in 'oldrel': 23 | addons: 24 | apt: 25 | packages: 26 | - libnlopt-dev 27 | 28 | env: 29 | global: 30 | - CRAN: http://cran.rstudio.com 31 | 32 | notifications: 33 | email: 34 | on_success: change 35 | on_failure: change 36 | -------------------------------------------------------------------------------- /DESCRIPTION: -------------------------------------------------------------------------------- 1 | Package: lmerTest 2 | Type: Package 3 | Title: Tests in Linear Mixed Effects Models 4 | Version: 3.1-3 5 | Authors@R: c(person("Alexandra", "Kuznetsova", role = c("aut")), 6 | person("Per", "Bruun Brockhoff", role = c("aut", "ths"), 7 | email = "perbb@dtu.dk"), 8 | person("Rune", "Haubo Bojesen Christensen", role = c("aut", "cre"), 9 | email = "Rune.Haubo@gmail.com"), 10 | person("Sofie", "Pødenphant Jensen", role=c("ctb"), email="sofp@dtu.dk")) 11 | Depends: 12 | R (>= 3.2.5), 13 | lme4 (>= 1.1-10), 14 | stats, 15 | methods 16 | Imports: 17 | numDeriv, 18 | MASS, 19 | ggplot2 20 | Suggests: 21 | pbkrtest (>= 0.4-3), 22 | tools 23 | Description: Provides p-values in type I, II or III anova and summary tables 24 | for lmer model fits (cf. lme4) via Satterthwaite's degrees of freedom method. A 25 | Kenward-Roger method is also available via the pbkrtest package. Model selection 26 | methods include step, drop1 and anova-like tables for random effects (ranova). 27 | Methods for Least-Square means (LS-means) and tests of linear contrasts of fixed 28 | effects are also available. 29 | License: GPL (>= 2) 30 | Encoding: UTF-8 31 | LazyData: true 32 | URL: https://github.com/runehaubo/lmerTestR 33 | BugReports: https://github.com/runehaubo/lmerTestR/issues 34 | RoxygenNote: 7.1.1 35 | Collate: 36 | 'anova_contrasts.R' 37 | 'contest.R' 38 | 'contrast_utils.R' 39 | 'data_documentation.R' 40 | 'drop1.R' 41 | 'estimability.R' 42 | 'legacy.R' 43 | 'lmer.R' 44 | 'lmerTest.R' 45 | 'lmer_anova.R' 46 | 'lmer_summary.R' 47 | 'ls_means.R' 48 | 'ranova.R' 49 | 'step.R' 50 | 'terms_utils.R' 51 | 'utils.R' 52 | -------------------------------------------------------------------------------- /NAMESPACE: -------------------------------------------------------------------------------- 1 | # Generated by roxygen2: do not edit by hand 2 | 3 | 4 | if(getRversion() >= "3.3.0") { 5 | importFrom("stats", sigma) 6 | } else { 7 | export(sigma) 8 | } 9 | 10 | S3method(anova,lmerModLmerTest) 11 | S3method(anova,merModLmerTest) 12 | S3method(as.data.frame,ls_means) 13 | S3method(contest,lmerMod) 14 | S3method(contest,lmerModLmerTest) 15 | S3method(contest1D,lmerMod) 16 | S3method(contest1D,lmerModLmerTest) 17 | S3method(contestMD,lmerMod) 18 | S3method(contestMD,lmerModLmerTest) 19 | S3method(difflsmeans,lmerModLmerTest) 20 | S3method(difflsmeans,merModLmerTest) 21 | S3method(drop1,lmerModLmerTest) 22 | S3method(drop1,merModLmerTest) 23 | S3method(get_model,step_list) 24 | S3method(ls_means,lmerModLmerTest) 25 | S3method(ls_means,merModLmerTest) 26 | S3method(lsmeansLT,lmerModLmerTest) 27 | S3method(lsmeansLT,merModLmerTest) 28 | S3method(plot,ls_means) 29 | S3method(plot,step_list) 30 | S3method(print,ls_means) 31 | S3method(print,step_list) 32 | S3method(show_tests,anova) 33 | S3method(show_tests,default) 34 | S3method(show_tests,ls_means) 35 | S3method(step,default) 36 | S3method(step,lmerModLmerTest) 37 | S3method(step,merModLmerTest) 38 | S3method(summary,lmerModLmerTest) 39 | S3method(summary,merModLmerTest) 40 | S3method(update,lmerModLmerTest) 41 | export(as_lmerModLmerTest) 42 | export(calcSatterth) 43 | export(contest) 44 | export(contest1D) 45 | export(contestMD) 46 | export(difflsmeans) 47 | export(get_model) 48 | export(lmer) 49 | export(ls_means) 50 | export(lsmeansLT) 51 | export(rand) 52 | export(ranova) 53 | export(show_tests) 54 | export(step) 55 | exportClasses(lmerModLmerTest) 56 | exportClasses(merModLmerTest) 57 | importClassesFrom(lme4,lmerMod) 58 | importFrom(MASS,fractions) 59 | importFrom(MASS,ginv) 60 | importFrom(ggplot2,aes) 61 | importFrom(ggplot2,element_text) 62 | importFrom(ggplot2,facet_wrap) 63 | importFrom(ggplot2,geom_bar) 64 | importFrom(ggplot2,geom_errorbar) 65 | importFrom(ggplot2,ggplot) 66 | importFrom(ggplot2,rel) 67 | importFrom(ggplot2,scale_fill_manual) 68 | importFrom(ggplot2,theme) 69 | importFrom(ggplot2,xlab) 70 | importFrom(ggplot2,ylab) 71 | importFrom(graphics,plot) 72 | importFrom(lme4,findbars) 73 | importFrom(lme4,fixef) 74 | importFrom(lme4,getME) 75 | importFrom(lme4,lmerControl) 76 | importFrom(lme4,nobars) 77 | importFrom(methods,as) 78 | importFrom(methods,callNextMethod) 79 | importFrom(methods,is) 80 | importFrom(methods,new) 81 | importFrom(methods,signature) 82 | importFrom(numDeriv,hessian) 83 | importFrom(numDeriv,jacobian) 84 | importFrom(stats,.getXlevels) 85 | importFrom(stats,.lm.fit) 86 | importFrom(stats,anova) 87 | importFrom(stats,as.formula) 88 | importFrom(stats,coef) 89 | importFrom(stats,delete.response) 90 | importFrom(stats,drop.scope) 91 | importFrom(stats,drop1) 92 | importFrom(stats,formula) 93 | importFrom(stats,getCall) 94 | importFrom(stats,lm.fit) 95 | importFrom(stats,logLik) 96 | importFrom(stats,model.frame) 97 | importFrom(stats,model.matrix) 98 | importFrom(stats,nobs) 99 | importFrom(stats,pchisq) 100 | importFrom(stats,pf) 101 | importFrom(stats,printCoefmat) 102 | importFrom(stats,pt) 103 | importFrom(stats,qt) 104 | importFrom(stats,resid) 105 | importFrom(stats,setNames) 106 | importFrom(stats,terms) 107 | importFrom(stats,update) 108 | importFrom(stats,update.formula) 109 | importFrom(stats,vcov) 110 | importFrom(utils,as.roman) 111 | importFrom(utils,combn) 112 | -------------------------------------------------------------------------------- /NEWS.md: -------------------------------------------------------------------------------- 1 | lmerTest 3.1-3 (October 2020) 2 | ------------------ 3 | 4 | - Update a test to accomodate `lme4::anova` reporting `NA` instead of `1` for p-value when df=0. 5 | - No longer print message about missing cells with mean centered covariates for type III anova tables (issue #19) 6 | - Fix step such that fixed effects are reduced even if all random effects are reduced away (issue #23). 7 | 8 | lmerTest 3.1-2 (April 2020) 9 | ------------------ 10 | 11 | - Remove argument "..." to accomodate new version of `lme4` (from version `1.1-22`) 12 | - Minor fix to tests to accomodate new version of `lme4` (from version `1.1-22`) 13 | 14 | lmerTest 3.1-1 15 | ------------------ 16 | 17 | - Sofie P Jensen is taking over as maintainer replacing Per B Brockhoff. 18 | - Fixing "noLD" CRAN issue (a check that ensures the package works on systems without long doubles). This was caused by an over sensitive test. 19 | 20 | lmerTest 3.1-0 21 | ------------------ 22 | 23 | - Adding support for legacy model fits, i.e. `merModLmerTest` objects generated with lmerTest version `< 3.0-0`. This includes defining the `merModLmerTest` class and `anova`, `summary`, `drop1`, `ls_means`, `lsmeansLT` and `difflsmeans` methods. The usual `lme4` methods also work with objects of class `merModLmerTest`. 24 | 25 | lmerTest 3.0-1 26 | ------------------ 27 | 28 | - over-sensitive tests (failing on Solaris) have reduced tolerance 29 | - `sigma` and `sigma.merMod` defined and exported for `R <= 3.3.0` 30 | - Warn if Kenward-Roger is used with `R <= 3.3.0` since it may give incorrect results 31 | - Add `lme4 (>= 1.1-10)` and `R (>= 3.2.5)` to `Depends` (last available version where `lmerTest` checks out) 32 | - `pbkrtest` package loaded conditional on availability in tests 33 | 34 | 35 | lmerTest 3.0-0 36 | ------------------ 37 | 38 | * The new and completely re-written lmerTest package. Details of changes are 39 | available in [pdf](https://github.com/runehaubo/lmerTestR/blob/master/pkg_notes/new_lmerTest.pdf) or [html](http://htmlpreview.github.io/?https://github.com/runehaubo/lmerTestR/blob/master/pkg_notes/new_lmerTest.html) 40 | 41 | 42 | lmerTest < 3.0-0 43 | ------------------ 44 | 45 | * Signficant news and changes for the 2.0-xx release series is provided below. 46 | 47 | 2.0-34 48 | 49 | - included citation info for JSS 50 | 51 | 2.0-33 52 | 53 | - lsmeans and difflsmeans are now deprecated functions. Changed the names to lsmeansLT and dlsmeansLT 54 | - changed the maintainer field 55 | 56 | 57 | 2.0-32 58 | 59 | - changed the message of identifiability to the more appropriate one 60 | 61 | 2.0-31 62 | 63 | - removed lmerTestFunctions.R and restructured the package. added calcSatterth(model, L) for calculating Satterthwaite's approximation for a specified L matrix 64 | 65 | 2.0-30 66 | 67 | - envir.R failed with the newest version of lme4. Changed the code to pass the check. TODO: remove updating the model 68 | 69 | 2.0-28 70 | 71 | - changes in general summary function. callNextMethod changed to as(model, "lmerMod) 72 | 73 | 2.0-25 74 | 75 | - updated according to comments from CRAN 76 | 77 | 2.0-24 changes: 78 | 79 | - cleaned the code 80 | 81 | 82 | 2.0-23 changes: 83 | 84 | - hessian and grad changed to mygrad and myhess (deriv.R functions of Rune) 85 | - plots use ggplot2 86 | - look for previous changes in R-Forge 87 | 88 | 2.0-11 changes: 89 | 90 | - elimRandEffs deleted. now the rand table contains all the information 91 | 92 | 2.0-9 changes: 93 | 94 | - fixed.calc option is added to step function 95 | - elimRand effs changed: random effects that are 1 approx to 1e-6 are eliminated 96 | - las=2 in barplots: verical axis names 97 | contrast with the name "l" changed to "l.lmerTest.private.contrasts" 98 | 99 | 2.0-8 changes: 100 | 101 | - throws error for lsmeans, difflsmeans, rand and step functions if the model does not inherit lmerMod class 102 | 103 | 2.0-7 changes: 104 | 105 | - in utils calcSatterth changed: solve of 0 dim matrix now catches in tryCatch - example MAMex.R in tests is added to check the bug 106 | - messages are printed if some computational errors occurr in anova or summary and the ones from lme4 are returned (bugSummary.R for testing) 107 | 108 | 2.0.6 changes: 109 | 110 | - added a number of tests in the tests folder and inst/datasets for the testing data sets - will not be included in the R-forge nor CRAN (for a moment) 111 | - model is not updated automatically to REML (tests for random effects are ML!) 112 | - man functions updated 113 | 114 | 2.0.5 changes: 115 | 116 | - fixed bug from Ben - summary(model, "lme4") changed to summary(model, ddf="lme4") 117 | - fixed bug for summary from Cyrus 118 | - added in manual notes regarding random coefficient models simplification 119 | - Rune changed solve to chol2inv in lmerTestFunctions.R 120 | - changed updateModel function so that the bugs with the environmentgs are solved 121 | 122 | 2.0.4 new: 123 | 124 | - rewritten rand table elimination 125 | - added elimrand.R 126 | 127 | 128 | Modifications in lmerTest 2.0.1 129 | 130 | - The elim.num column now has KEEP instead of 0 131 | - X'X deficiancy was fixed by Rune, lmerTest was fixed accordingly 132 | -------------------------------------------------------------------------------- /R/data_documentation.R: -------------------------------------------------------------------------------- 1 | ############################################################################# 2 | # Copyright (c) 2013-2020 Alexandra Kuznetsova, Per Bruun Brockhoff, and 3 | # Rune Haubo Bojesen Christensen 4 | # 5 | # This file is part of the lmerTest package for R (*lmerTest*) 6 | # 7 | # *lmerTest* is free software: you can redistribute it and/or modify 8 | # it under the terms of the GNU General Public License as published by 9 | # the Free Software Foundation, either version 2 of the License, or 10 | # (at your option) any later version. 11 | # 12 | # *lmerTest* is distributed in the hope that it will be useful, 13 | # but WITHOUT ANY WARRANTY; without even the implied warranty of 14 | # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 15 | # GNU General Public License for more details. 16 | # 17 | # A copy of the GNU General Public License is available at 18 | # and/or 19 | # . 20 | ############################################################################# 21 | # 22 | # data_documentation.R - roxygen2 documentation for datasets. 23 | 24 | # Datasets documented in this file: 25 | # 26 | # - carrots 27 | # - ham 28 | # - TVbo 29 | 30 | ############################################## 31 | ######## carrots 32 | ############################################## 33 | #' Consumer Preference Mapping of Carrots 34 | #' 35 | #' In a consumer study 103 consumers scored their preference of 12 danish 36 | #' carrot types on a scale from 1 to 7. Moreover the consumers scored the 37 | #' degree of sweetness, bitterness and crispiness in the products. 38 | #' 39 | #' The carrots were harvested in autumn 1996 and tested in march 1997. In 40 | #' addition to the consumer survey, the carrot products were evaluated by 41 | #' a trained panel of tasters, the sensory panel, with respect to a 42 | #' number of sensory (taste, odour and texture) properties. Since usually 43 | #' a high number of (correlated) properties (variables) are used, in this 44 | #' case 14, it is a common procedure to use a few, often 2, combined 45 | #' variables that contain as much of the information in the sensory 46 | #' variables as possible. This is achieved by extracting the first two 47 | #' principal components in a principal components analysis (PCA) on the 48 | #' product-by-property panel average data matrix. In this data set the 49 | #' variables for the first two principal components are named 50 | #' (\code{sens1} and \code{sens2}). 51 | #' 52 | #' @docType data 53 | #' 54 | #' @usage data(carrots) 55 | #' 56 | #' @format 57 | #' \describe{ 58 | #' \item{Consumer}{factor with 103 levels: numbering identifying consumers.} 59 | #' \item{Frequency}{factor with 5 levels; "How often do you eat carrots?" 60 | #' 1: once a week or more, 2: once 61 | #' every two weeks, 3: once every three weeks, 4: at least once month, 62 | #' 5: less than once a month.} 63 | #' \item{Gender}{factor with 2 levels. 1: male, 2:female.} 64 | #' \item{Age}{factor with 4 levels. 1: less than 25 years, 2: 26-40 years, 65 | #' 3: 41-60 years, 4 more than 61 years.} 66 | #' \item{Homesize}{factor with two levels. Number of persons in the household. 67 | #' 1: 1 or 2 persons, 2: 3 or more persons.} 68 | #' \item{Work}{factor with 7 levels. different types of employment. 69 | #' 1: unskilled worker(no education), 70 | #' 2: skilled worker(with education), 3: office worker, 4: housewife (or man), 71 | #' 5: independent 72 | #' businessman/ self-employment, 6: student, 7: retired} 73 | #' \item{Income}{factor with 4 levels. 1: <150000, 2: 150000-300000, 74 | #' 3: 300000-500000, 4: >500000} 75 | #' \item{Preference}{consumer score on a seven-point scale.} 76 | #' \item{Sweetness}{consumer score on a seven-point scale.} 77 | #' \item{Bitterness}{consumer score on a seven-point scale.} 78 | #' \item{Crispness}{consumer score on a seven-point scale.} 79 | #' \item{sens1}{first sensory variable derived from a PCA.} 80 | #' \item{sens2}{second sensory variable derived from a PCA.} 81 | #' \item{Product}{factor on 12 levels.} 82 | #' } 83 | #' 84 | #' @keywords datasets 85 | #' @source Per Bruun Brockhoff, The Royal Veterinary and Agricultural University, 86 | #' Denmark. 87 | #' 88 | #' @examples 89 | #' 90 | #' fm <- lmer(Preference ~ sens2 + Homesize + (1 + sens2 | Consumer), data=carrots) 91 | #' anova(fm) 92 | #' 93 | "carrots" 94 | 95 | 96 | ############################################## 97 | ######## ham 98 | ############################################## 99 | #' Conjoint Study of Dry Cured Ham 100 | #' 101 | #' One of the purposes of the study was to investigate the effect of 102 | #' information given to the consumers measured in hedonic liking for the 103 | #' hams. Two of the hams were Spanish and two were Norwegian, each origin 104 | #' representing different salt levels and different aging time. The 105 | #' information about origin was given in such way that both true and 106 | #' false information was given. Essentially a 4x2 design with 4 samples 107 | #' and 2 information levels. A total of 81 Consumers participated in the 108 | #' study. 109 | #' 110 | #' @docType data 111 | #' 112 | #' @usage data(ham) 113 | #' 114 | #' @format 115 | #' \describe{ 116 | #' \item{Consumer}{factor with 81 levels: numbering identifying consumers.} 117 | #' \item{Product}{factor with four levels.} 118 | #' \item{Informed.liking}{numeric: hedonic liking for the products.} 119 | #' \item{Information}{factor with two levels.} 120 | #' \item{Gender}{factor with two levels.} 121 | #' \item{Age}{numeric: age of Consumer.} 122 | #' } 123 | #' 124 | #' @keywords datasets 125 | #' 126 | #' @references 127 | #' T. Næs, V. Lengard, S. Bølling Johansen, M. Hersleth (2010) 128 | #' Alternative methods for combining design variables and consumer preference 129 | #' with information about attitudes and demographics in conjoint analysis, 130 | #' \emph{Food Quality and Preference}, 10-4, 368-378, ISSN 0950-3293, 131 | #' \url{https://doi.org/10.1016/j.foodqual.2009.09.004}. 132 | #' 133 | #' @examples 134 | #' 135 | #' # Simple model for the ham data: 136 | #' fm <- lmer(Informed.liking ~ Product*Information + (1|Consumer) , data=ham) 137 | #' 138 | #' # Anova table for the fixed effects: 139 | #' anova(fm) 140 | #' 141 | #' \dontrun{ 142 | #' # Fit 'big' model: 143 | #' fm <- lmer(Informed.liking ~ Product*Information*Gender*Age + 144 | #' + (1|Consumer) + (1|Consumer:Product) + 145 | #' (1|Consumer:Information), 146 | #' data=ham) 147 | #' step_fm <- step(fm) 148 | #' step_fm # Display elimination results 149 | #' final_fm <- get_model(step_fm) 150 | #' } 151 | #' 152 | "ham" 153 | 154 | 155 | ############################################## 156 | ######## TVbo 157 | ############################################## 158 | #' Sensory Assesment of B&O TVs 159 | #' 160 | #' The TVbo dataset has kindly been made available by the Danish high-end 161 | #' consumer electronics company 162 | #' \href{https://www.bang-olufsen.com}{Bang & Olufsen}. 163 | #' The main purpose was to assess 12 different TV sets (products) specified by 164 | #' the two attributes Picture and TVset. 165 | #' 15 different response variables (characteristics of the 166 | #' product) were assessed by a trained panel with 8 assessors. 167 | #' 168 | #' @format 169 | #' \describe{ 170 | #' \item{Assessor}{factor with 8 levels assessors.} 171 | #' \item{TVset}{product factor with 3 levels.} 172 | #' \item{Picture}{product factor with 4 levels.} 173 | #' } 174 | #' In addition the following 15 numeric (response) variables are the 175 | #' characteristics on which the TV sets (products) are assessed: 176 | #' 177 | #' Coloursaturation, Colourbalance, Noise, Depth, Sharpness, Lightlevel, 178 | #' Contrast, Sharpnessofmovement, Flickeringstationary, Flickeringmovement, 179 | #' Distortion, Dimglasseffect, Cutting, Flossyedges, Elasticeffect. 180 | #' 181 | #' @docType data 182 | #' 183 | #' @usage data(TVbo) 184 | #' 185 | #' @examples 186 | #' 187 | #' fm <- lmer(Coloursaturation ~ TVset + Picture + (1|Assessor:TVset) + 188 | #' (1|Assessor), data=TVbo) 189 | #' ranova(fm) 190 | #' anova(fm) 191 | #' 192 | "TVbo" 193 | -------------------------------------------------------------------------------- /R/drop1.R: -------------------------------------------------------------------------------- 1 | ############################################################################# 2 | # Copyright (c) 2013-2020 Alexandra Kuznetsova, Per Bruun Brockhoff, and 3 | # Rune Haubo Bojesen Christensen 4 | # 5 | # This file is part of the lmerTest package for R (*lmerTest*) 6 | # 7 | # *lmerTest* is free software: you can redistribute it and/or modify 8 | # it under the terms of the GNU General Public License as published by 9 | # the Free Software Foundation, either version 2 of the License, or 10 | # (at your option) any later version. 11 | # 12 | # *lmerTest* is distributed in the hope that it will be useful, 13 | # but WITHOUT ANY WARRANTY; without even the implied warranty of 14 | # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 15 | # GNU General Public License for more details. 16 | # 17 | # A copy of the GNU General Public License is available at 18 | # and/or 19 | # . 20 | ############################################################################# 21 | # 22 | # drop1.R - drop1 method for lmerModLmerTest objects 23 | 24 | # ------- Contents: -------- 25 | # 26 | # drop1.lmerModLmerTest 27 | # 28 | # --- Utility functions: --- 29 | # 30 | # get_Ldiffmat 31 | # get_Ldiffmat2 32 | # 33 | 34 | ############################################## 35 | ######## drop1.lmerModLmerTest 36 | ############################################## 37 | #' Drop Marginal Terms from Model 38 | #' 39 | #' Computes the F-test for all marginal terms, i.e. terms that can be dropped 40 | #' from the model while respecting the hierarchy of terms in the model. 41 | #' 42 | #' Simple marginal contrasts are used for all marginal terms unless the design 43 | #' matrix is rank deficient. In that case (and if \code{force_get_contrasts} is 44 | #' \code{TRUE}) the contrasts (i.e. restriction matrices on the design matrix 45 | #' of the full model) are computed by comparison of the design matrices 46 | #' for full and restricted models. The set of marginal terms considered for 47 | #' dropping are computed using \code{drop.scope(terms(object))}. 48 | #' 49 | #' Since all tests are based on tests of contrasts in the full model, no 50 | #' models are being (re)fitted. 51 | #' 52 | #' @param object an \code{\link{lmer}} model fit (of class 53 | #' \code{"lmerModLmerTest"}.) 54 | #' @param scope optional character vector naming terms to be dropped from the 55 | #' model. Note that only marginal terms can be dropped. To see which terms are 56 | #' marginal, use \code{drop.scope(terms(object))}. 57 | #' @param ddf the method for computing the denominator degrees of freedom and 58 | #' F-statistics. \code{ddf="Satterthwaite"} (default) uses Satterthwaite's method; 59 | #' \code{ddf="Kenward-Roger"} uses Kenward-Roger's method. 60 | #' \code{ddf = "lme4"} returns the \code{drop1} table for \code{merMod} objects 61 | #' as defined in package \pkg{lme4}. 62 | #' @param force_get_contrasts enforce computation of contrast matrices by a 63 | #' method in which the design matrices for full and restricted models are 64 | #' compared. 65 | #' @param ... currently not used. 66 | #' 67 | #' @author Rune Haubo B. Christensen 68 | #' @seealso \code{\link{ranova}} for tests of marginal random terms. 69 | #' @return An anova-like table with F-tests of marginal terms. 70 | #' @export 71 | #' 72 | #' @importFrom stats drop1 drop.scope terms formula 73 | #' @examples 74 | #' 75 | #' # Basic usage: 76 | #' fm <- lmer(angle ~ recipe + temp + (1|recipe:replicate), cake) 77 | #' drop1(fm) # Using Satterthwaite degrees of freedom 78 | #' if(requireNamespace("pbkrtest", quietly = TRUE)) 79 | #' drop1(fm, ddf="Kenward-Roger") # Alternative DenDF and F-test method 80 | #' drop1(fm, ddf="lme4", test="Chi") # Asymptotic Likelihood ratio tests 81 | #' 82 | #' # Consider a rank-deficient design matrix: 83 | #' fm <- lmer(angle ~ recipe + temp + temperature + (1|recipe:replicate), cake) 84 | #' # Here temp accounts for the linear effect of temperature, and 85 | #' # temperature is an (ordered) factor that accounts for the remaining 86 | #' # variation between temperatures (4 df). 87 | #' drop1(fm) 88 | #' # While temperature is in the model, we cannot test the effect of dropping 89 | #' # temp. After removing temperature we can test the effect of dropping temp: 90 | #' drop1(lmer(angle ~ recipe + temp + (1|recipe:replicate), cake)) 91 | #' 92 | #' # Polynomials: 93 | #' # Note that linear terms should usually not be dropped before squared terms. 94 | #' # Therefore 'Days' should not be dropped before 'I(Days^2)' despite it being 95 | #' # tested here: 96 | #' fm <- lmer(Reaction ~ Days + I(Days^2) + (Days|Subject), sleepstudy) 97 | #' drop1(fm) 98 | #' # Using poly() provides a test of the whole polynomial structure - not a 99 | #' # separate test for the highest order (squared) term: 100 | #' fm <- lmer(Reaction ~ poly(Days, 2) + (Days|Subject), sleepstudy) 101 | #' drop1(fm) 102 | #' 103 | drop1.lmerModLmerTest <- function(object, scope, ddf=c("Satterthwaite", "Kenward-Roger", "lme4"), 104 | force_get_contrasts=FALSE, ...) { 105 | ddf <- match.arg(ddf) 106 | if(ddf == "lme4") return(NextMethod()) 107 | marg_terms <- drop.scope(terms(object)) 108 | if(missing(scope)) scope <- marg_terms else { 109 | if(length(scope) == 0 || !is.character(scope)) 110 | stop("'scope' should be a character vector naming terms to be dropped") 111 | if(!all(scope %in% marg_terms)) 112 | stop("Only marginal terms can be dropped from the model") 113 | } 114 | # Get contrasts for marginal terms: 115 | X <- model.matrix(object) 116 | Llist <- get_contrasts_marginal(object) 117 | if(length(scope)) { 118 | Llist <- Llist[scope] # retain contrasts for terms in scope 119 | if(!is.null(attr(X, "col.dropped")) || force_get_contrasts) { 120 | # Compute L directly if model is rank deficient or force_get_contrasts is TRUE: 121 | orig_form <- formula(object) 122 | new_forms <- lapply(rm_complete_terms(scope, orig_form, random=FALSE), nobars) 123 | # Compute list of contrast matrices as 'diffs' to orig. X: 124 | Llist <- if(!length(new_forms)) list() else 125 | lapply(new_forms, function(form) { 126 | suppressWarnings(x <- model.matrix(form[-2], data=model.frame(object), 127 | contrasts.arg = attr(X, "contrasts"))) 128 | L <- get_Ldiffmat2(x, X) # L may be length 0 if x == X (rank-deficint fits.) 129 | if(!length(L)) rep(NA_real_, ncol(X)) else L 130 | }) 131 | } 132 | } 133 | # Compute anova-like table: 134 | aov <- rbindall(lapply(Llist, function(L) contestMD(object, L, ddf = ddf))) 135 | # Format results: 136 | method <- switch(ddf, "Satterthwaite" = "Satterthwaite's", 137 | "Kenward-Roger" = "Kenward-Roger's") 138 | attr(aov, "heading") <- 139 | c(paste("Single term deletions using", method, "method:"), 140 | "\nModel:", deparse2(formula(object))) 141 | attr(aov, "hypotheses") <- Llist 142 | attr(aov, "ddf") <- ddf 143 | class(aov) <- c("anova", "data.frame") 144 | aov 145 | } 146 | 147 | 148 | get_Ldiffmat <- function(A0, A) { 149 | Rank <- function(X) qr(X)$rank 150 | Q <- qr.Q(qr(cbind(A0, A))) 151 | rA0 <- Rank(A0) 152 | rA <- Rank(A) 153 | set <- if(rA0 < rA) (rA0+1):rA else numeric(0L) 154 | Q2 <- Q[, set, drop=FALSE] 155 | L <- t(Q2) %*% A 156 | L <- t(qr.Q(qr(t(L)))) # Orthonormalize contrast 157 | L 158 | } 159 | 160 | #' @importFrom stats .lm.fit resid 161 | get_Ldiffmat2 <- function(X0, X) { 162 | # X : design matrix for the full model 163 | # X0: design matrix for the restricted model 164 | # R is the residual of the orthogonal projection of X on X0, thus 165 | # R is orthogonal to X0 and a subspace of X, and 166 | # Lt is a restriction matrix on X. 167 | R <- resid(.lm.fit(x=X0, y=X)) 168 | R <- R[, colSums(abs(R)) > 1e-8] 169 | Lt <- crossprod(X, R) 170 | Lt[] <- zapsmall(qr.Q(qr(Lt))) # orthonormalize contrasts 171 | t(Lt) 172 | } 173 | -------------------------------------------------------------------------------- /R/estimability.R: -------------------------------------------------------------------------------- 1 | ############################################################################# 2 | # Copyright (c) 2013-2020 Alexandra Kuznetsova, Per Bruun Brockhoff, and 3 | # Rune Haubo Bojesen Christensen 4 | # 5 | # This file is part of the lmerTest package for R (*lmerTest*) 6 | # 7 | # *lmerTest* is free software: you can redistribute it and/or modify 8 | # it under the terms of the GNU General Public License as published by 9 | # the Free Software Foundation, either version 2 of the License, or 10 | # (at your option) any later version. 11 | # 12 | # *lmerTest* is distributed in the hope that it will be useful, 13 | # but WITHOUT ANY WARRANTY; without even the implied warranty of 14 | # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 15 | # GNU General Public License for more details. 16 | # 17 | # A copy of the GNU General Public License is available at 18 | # and/or 19 | # . 20 | ############################################################################# 21 | # 22 | # estimability.R - functions for assessing model estimability 23 | 24 | # ------- Contents: -------- 25 | # 26 | # is_estimable 27 | # nullspace 28 | # 29 | 30 | 31 | ############################################## 32 | ######## is_estimable 33 | ############################################## 34 | #' Estimability of Contrasts 35 | #' 36 | #' Computes the estimability of a vector or matrix of contrasts (i.e. linear 37 | #' functions of the coefficients) from the nullspace of a design matrix or 38 | #' potentially directly from the design matrix. 39 | #' 40 | #' @param contrast a numeric matrix where each row is a contrast vector for 41 | #' which estimability is computed. The matrix should have as many columns as 42 | #' there are columns in the design matrix (which equals the number of 43 | #' coefficients). If \code{contrast} is a vector it is coerced to a matrix. 44 | #' @param nullspace the nullspace of the design matrix. 45 | #' @param X design matrix. 46 | #' @param tol tolerance for determining if a contrast is orthogonal to the 47 | # nullspace. 48 | #' 49 | #' @return a logical vector of length \code{nrow(contrast)} determining if each 50 | #' contrast is estimable 51 | #' @importFrom stats setNames 52 | #' @keywords internal 53 | #' @seealso \code{\link{nullspace}} 54 | #' 55 | #' @author Rune Haubo B. Christensen 56 | #' @keywords internal 57 | #' @examples 58 | #' 59 | #' # FIXME: We need some examples here 60 | #' 61 | is_estimable <- function(contrast, nullspace=NULL, X=NULL, 62 | tol=sqrt(.Machine$double.eps)) { 63 | if(!is.matrix(contrast)) contrast <- matrix(contrast, ncol=length(contrast)) 64 | N <- if(!is.null(nullspace)) { # get nullspace 65 | nullspace 66 | } else if(!is.null(X)) { 67 | nullspace(X) 68 | } else { 69 | stop("Need non-null 'nullspace' or 'X' to compute estimability") 70 | } 71 | if(ncol(contrast) != nrow(N)) 72 | stop(sprintf("'contrast' has %i columns: expecting %i columns", 73 | ncol(contrast), nrow(N))) 74 | # Determine estimability: 75 | res <- if(length(N) == 0) rep(TRUE, nrow(contrast)) else 76 | c(abs(rowSums(contrast %*% N)) < tol) 77 | setNames(res, rownames(contrast)) 78 | } 79 | # 80 | # XX <- model.matrix(terms(model), data=model.frame(model)) 81 | # nullspaceX <- nullspace(XX) 82 | # is_estimable(Llist$DAY, nullspaceX) 83 | # is_estimable(c(Llist$DAY[1, ]), nullspaceX) 84 | # is_estimable(Llist$DAY, X=XX) 85 | # NCOL(0:1) 86 | # 87 | # X <- model.matrix(model) 88 | # str(Llist$DAY[, -9] %*% nullspace(X)) 89 | # is_estimable(Llist$DAY[, -9], X=X) 90 | # is_estimable(0:1, X=X) 91 | # contrast <- 0:1 92 | # nrow(matrix(0:1, ncol=2)) 93 | # rep(TRUE, 1) 94 | # 95 | # length(Llist$DAY[, -9] %*% nullspace(X)) 96 | # apply(Llist$DAY[, -9] %*% nullspace(X), 1, length) 97 | # length(nullspace(X)) 98 | 99 | ############################################## 100 | ######## nullspace 101 | ############################################## 102 | #' Nullspace 103 | #' 104 | #' Compute the (right or left) nullspace of matrix using a (semi-complete) 105 | #' Singular Value Decomposition. 106 | #' 107 | #' This implementation is fastest on matrices with more rows 108 | #' than columns such as a typical design matrix for a linear model. 109 | #' 110 | #' @param A a numeric matrix. 111 | #' @param type \code{"right"} (default) gives is the standard nullspace, 112 | #' \code{"left"} gives left nullspace of \code{A}. 113 | #' @param tol tolerance multiple of the first singular value to determine if 114 | #' subsequent singular values are (sufficiently) positive to be determined 115 | #' greater than zero. 116 | #' 117 | #' @return a matrix with as many rows as there are columns in \code{A}. The 118 | #' number of columns (which may be zero) determine the dimensionality of the 119 | #' nullspace of \code{A}. 120 | #' @author Rune Haubo B. Christensen 121 | #' 122 | #' @keywords internal 123 | #' @examples 124 | #' 125 | #' # FIXME: We need some examples here 126 | #' 127 | nullspace <- function(A, type = c("right", "left"), 128 | tol=sqrt(.Machine$double.eps)) { 129 | # Compute the right (standard and default) or left null space of a matrix A. 130 | # using SVD. 131 | type <- match.arg(type) 132 | if(type == "left") return(nullspace(t(A), type="right", tol=tol)) 133 | if(length(A) == 0L) return(matrix(numeric(0L))) # length(A) == 0 if any(dim(A) == 0) 134 | svdA <- svd(A, nv = ncol(A)) 135 | tol <- 1e-8 136 | positive <- svdA$d > max(tol * svdA$d[1L], 0) 137 | rank <- sum(positive) 138 | set <- if(rank == 0) 1:ncol(A) else -(1:rank) 139 | svdA$v[, set, drop=FALSE] 140 | } 141 | 142 | 143 | -------------------------------------------------------------------------------- /R/legacy.R: -------------------------------------------------------------------------------- 1 | ############################################################################# 2 | # Copyright (c) 2013-2020 Alexandra Kuznetsova, Per Bruun Brockhoff, and 3 | # Rune Haubo Bojesen Christensen 4 | # 5 | # This file is part of the lmerTest package for R (*lmerTest*) 6 | # 7 | # *lmerTest* is free software: you can redistribute it and/or modify 8 | # it under the terms of the GNU General Public License as published by 9 | # the Free Software Foundation, either version 2 of the License, or 10 | # (at your option) any later version. 11 | # 12 | # *lmerTest* is distributed in the hope that it will be useful, 13 | # but WITHOUT ANY WARRANTY; without even the implied warranty of 14 | # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 15 | # GNU General Public License for more details. 16 | # 17 | # A copy of the GNU General Public License is available at 18 | # and/or 19 | # . 20 | ############################################################################# 21 | # 22 | # legacy.R - support for lecacy 'merModLmerTest' objects. 23 | 24 | # ------- Contents: -------- 25 | # 26 | # --- Classes: --- 27 | # 28 | # merModLmerTest 29 | # 30 | # --- methods: --- 31 | # 32 | # anova.merModLmerTest 33 | # summary.merModLmerTest 34 | # ls_means.merModLmerTest 35 | # lsmeansLT.merModLmerTest 36 | # difflsmeans.merModLmerTest 37 | # drop1.merModLmerTest 38 | # 39 | 40 | ############################################## 41 | ######## merModLmerTest class 42 | ############################################## 43 | #' Legacy lmerTest representation of Linear Mixed-Effects Models 44 | #' 45 | #' The \code{merModLmerTest} class extends \code{lmerMod} (which extends 46 | #' \code{merMod}) from the \pkg{lme4}-package. 47 | #' 48 | #' @export 49 | #' @keywords internal 50 | #' @author Rune Haubo B. Christensen 51 | #' @importClassesFrom lme4 lmerMod 52 | merModLmerTest <- setClass("merModLmerTest", contains = c("lmerMod")) 53 | 54 | ############################################## 55 | ######## anova method for merModLmerTest 56 | ############################################## 57 | #' Methods for Legacy lmerTest Objects 58 | #' 59 | #' Methods are defined for legacy lmerTest objects of class 60 | #' \code{merModLmerTest} generated with \pkg{lmerTest} version \code{< 3.0-0}. 61 | #' These methods are defined by interfacing code for \code{lmerModLmerTest} 62 | #' methods and therefore behaves like these methods do (which may differ from 63 | #' the behavior of \pkg{lmerTest} version \code{< 3.0-0}.) 64 | #' 65 | #' @inheritParams anova.lmerModLmerTest 66 | #' @param ... for the anova method optionally additional models; for other 67 | #' methods see the corresponding \code{lmerModLmerTest} methods for details. 68 | #' @rdname legacy 69 | #' @aliases legacy 70 | #' @keywords internal 71 | #' @author Rune Haubo B. Christensen 72 | #' @export 73 | #' @examples 74 | #' # Load model fits fm1 and fm2 generated with lmerTest version 2.3-37: 75 | #' load(system.file("testdata","legacy_fits.RData", package="lmerTest")) 76 | #' 77 | #' # Apply some methods defined by lmerTest: 78 | #' anova(fm1) 79 | #' summary(fm1) 80 | #' contest(fm1, c(0, 1)) 81 | #' contest(fm1, c(0, 1), joint=FALSE) 82 | #' drop1(fm1) 83 | #' ranova(fm1) 84 | #' 85 | #' # lme4-methods also work: 86 | #' fixef(fm1) 87 | #' 88 | #' # Ditto for second model fit: 89 | #' anova(fm2) 90 | #' summary(fm2) 91 | #' ls_means(fm2) 92 | #' difflsmeans(fm2) 93 | anova.merModLmerTest <- function(object, ..., type = c("III", "II", "I", "3", "2", "1"), 94 | ddf = c("Satterthwaite", "Kenward-Roger", "lme4")) { 95 | class(object) <- "lmerMod" 96 | dots <- list(...) 97 | models <- if (length(dots)) 98 | sapply(dots, is, "merModLmerTest") | sapply(dots, is, "lmerModLmerTest") | 99 | sapply(dots, is, "merMod") | sapply(dots, is, "lm") 100 | else logical(0) 101 | if(any(models)) return(NextMethod()) 102 | df <- match.arg(ddf) 103 | if (df == "lme4") 104 | return(anova(object, ...)) 105 | 106 | object <- as_lmerModLmerTest(object) 107 | anova(object, ..., type=type, ddf=ddf) 108 | } 109 | 110 | ############################################## 111 | ######## summary method for merModLmerTest 112 | ############################################## 113 | #' @rdname legacy 114 | #' @export 115 | summary.merModLmerTest <- function(object, ..., 116 | ddf=c("Satterthwaite", "Kenward-Roger", "lme4")) { 117 | class(object) <- "lmerMod" 118 | object <- as_lmerModLmerTest(object) 119 | summary.lmerModLmerTest(object=object, ..., ddf=ddf) 120 | } 121 | 122 | ############################################## 123 | ######## ls_means method for merModLmerTest 124 | ############################################## 125 | #' @rdname legacy 126 | #' @inheritParams ls_means.lmerModLmerTest 127 | #' @export 128 | ls_means.merModLmerTest <- function(model, which=NULL, level=0.95, 129 | ddf=c("Satterthwaite", "Kenward-Roger"), 130 | pairwise=FALSE, ...) { 131 | class(model) <- "lmerMod" 132 | model <- as_lmerModLmerTest(model) 133 | ls_means(model=model, which=which, level=level, ddf=ddf, pairwise=pairwise) 134 | } 135 | 136 | ############################################## 137 | ######## lsmeansLT method for merModLmerTest 138 | ############################################## 139 | #' @rdname legacy 140 | #' @export 141 | lsmeansLT.merModLmerTest <- ls_means.merModLmerTest 142 | 143 | ############################################## 144 | ######## difflsmeans method for merModLmerTest 145 | ############################################## 146 | #' @rdname legacy 147 | #' @export 148 | difflsmeans.merModLmerTest <- function(model, which=NULL, level=0.95, 149 | ddf=c("Satterthwaite", "Kenward-Roger"), ...) { 150 | ls_means(model, which=which, level=level, ddf=ddf, pairwise = TRUE) 151 | } 152 | 153 | ############################################## 154 | ######## drop1 method for merModLmerTest 155 | ############################################## 156 | #' @rdname legacy 157 | #' @inheritParams drop1.lmerModLmerTest 158 | #' @export 159 | drop1.merModLmerTest <- function(object, scope, ddf=c("Satterthwaite", "Kenward-Roger", "lme4"), 160 | force_get_contrasts=FALSE, ...) { 161 | class(object) <- "lmerMod" 162 | object <- as_lmerModLmerTest(object) 163 | drop1(object=object, scope=scope, ddf=ddf, force_get_contrasts=FALSE, ...) 164 | } 165 | 166 | ############################################## 167 | ######## step method for merModLmerTest 168 | ############################################## 169 | #' @rdname legacy 170 | #' @inheritParams step.lmerModLmerTest 171 | #' @export 172 | step.merModLmerTest <- function(object, ddf=c("Satterthwaite", "Kenward-Roger"), 173 | alpha.random=0.1, alpha.fixed=0.05, 174 | reduce.fixed=TRUE, reduce.random=TRUE, 175 | keep, ...) { 176 | class(object) <- "lmerMod" 177 | object <- as_lmerModLmerTest(object) 178 | step(object, ddf=ddf, alpha.random=alpha.random, alpha.fixed=alpha.fixed, 179 | reduce.fixed=reduce.fixed, reduce.random=reduce.random, 180 | keep=keep, ...) 181 | } 182 | -------------------------------------------------------------------------------- /R/lmerTest.R: -------------------------------------------------------------------------------- 1 | ############################################################################# 2 | # Copyright (c) 2013-2020 Alexandra Kuznetsova, Per Bruun Brockhoff, and 3 | # Rune Haubo Bojesen Christensen 4 | # 5 | # This file is part of the lmerTest package for R (*lmerTest*) 6 | # 7 | # *lmerTest* is free software: you can redistribute it and/or modify 8 | # it under the terms of the GNU General Public License as published by 9 | # the Free Software Foundation, either version 2 of the License, or 10 | # (at your option) any later version. 11 | # 12 | # *lmerTest* is distributed in the hope that it will be useful, 13 | # but WITHOUT ANY WARRANTY; without even the implied warranty of 14 | # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 15 | # GNU General Public License for more details. 16 | # 17 | # A copy of the GNU General Public License is available at 18 | # and/or 19 | # . 20 | ############################################################################# 21 | # 22 | # lmerTest.R - package documentation page 23 | 24 | #' lmerTest: Tests in Linear Mixed Effects Models 25 | #' 26 | #' The \pkg{lmerTest} package provides p-values in type I, II or III 27 | #' \code{anova} and \code{summary} 28 | #' tables for linear mixed models (\code{\link{lmer}} model fits cf. \pkg{lme4}) 29 | #' via Satterthwaite's degrees of freedom method; a Kenward-Roger method is also 30 | #' available via the \pkg{pbkrtest} package. 31 | #' Model selection and assessment methods include \code{\link{step}}, 32 | #' \code{\link{drop1}}, anova-like tables for random effects (\code{\link{ranova}}), 33 | #' least-square means (LS-means; \code{\link{ls_means}}) 34 | #' and tests of linear contrasts of fixed effects (\code{\link{contest}}). 35 | #' 36 | #' 37 | #' @section Key Functions and Methods: 38 | #' 39 | #' \describe{ 40 | #' \item{lmer}{overloads \code{lme4::lmer} and produced an object of class 41 | #' \code{lmerModLmerTest} which inherits from \code{lmerMod}. In addition to 42 | #' computing the model (using \code{lme4::lmer}), \code{lmerTest::lmer} 43 | #' computes a couple of components needed for the evaluation of Satterthwaite's 44 | #' denominator degrees of freedom.} 45 | #' \item{anova}{anova method for \code{\link{lmer}} model fits produces 46 | #' type I, II, and III anova tables for fixed-effect terms with 47 | #' Satterthwaite and Kenward-Roger methods for denominator degrees of freedom 48 | #' for F-tests.} 49 | #' \item{summary}{summary method for \code{\link{lmer}} model fits adds 50 | #' denominator degrees of freedom and p-values to the coefficient table.} 51 | #' \item{ranova}{anova-like table of random effects via likelihood ratio tests 52 | #' with methods for both \code{lmerMod} and \code{lmerModLmerTest} objects. 53 | #' \code{ranova} can either test reduction of random-effect terms to simpler 54 | #' structures or it can test removal of entire random-effect terms.} 55 | #' \item{drop1}{F-tests of fixed-effect terms using Satterthwaite or 56 | #' Kenward-Roger methods for denominator degrees of freedom. These 'single term 57 | #' deletion' tables are useful for model selection and tests of marginal terms. 58 | #' Compared to the likelihood ratio tests of \code{lme4::drop1} the F-tests and 59 | #' p-values of \code{lmerTest::drop1} are more accurate and considerably faster 60 | #' since no additional model fitting is required.} 61 | #' \item{contest}{tests of contrasts, i.e. tests of linear functions of the 62 | #' fixed-effect coefficients. A user-friendly interface for tests of contrasts 63 | #' with outputs either as a summary-like table of t-tests or an anova-like table 64 | #' of F-tests (or a list of either). Contrasts can optionally be tested for 65 | #' estimability. Contrasts are allowed to be rank-deficient as the rank is 66 | #' automatically detected and appropriate adjustments made. Methods for 67 | #' \code{lmerModLmerTest} as well as \code{lmerMod} objects -- the latter avoids 68 | #' the Satterthwaite specific computations when the Kenward-Roger method is used.} 69 | #' \item{show_test}{a function which operates on anova tables and LS-means tables 70 | #' makes it possible to see exactly which 71 | #' functions of the coefficients are being tested. This is helpful when 72 | #' differences between type I, II and III anova tables are being considered and 73 | #' discussed.} 74 | #' \item{ls_means}{computes the so-called least-squares means (classical Yates 75 | #' contrasts) as well as pairwise differences of these.} 76 | #' \item{step}{performs automatic backward model selection of fixed and random 77 | #' parts of the linear mixed model.} 78 | #' \item{as_lmerModLmerTest}{an explicit coerce function from class 79 | #' \code{lmerMod} to \code{lmerModLmerTest}.} 80 | #' } 81 | #' 82 | #' @section Details: 83 | #' The computational approach is to let \code{lmerTest::lmer} compute the 84 | #' Hessian and derivatives needed for evaluation of degrees of freedom and 85 | #' t- and F-tests and to store these in the model object. The 86 | #' Hessian and derivatives are therefore computed only once per model fit 87 | #' and reused with each call to \code{anova}, \code{summary}, etc. Evaluation of 88 | #' t and F-tests does not involve model re-fitting. 89 | #' 90 | #' \code{lmerTest::lmer} roughly amounts to calling \code{lme4::lmer} followed by 91 | #' \code{lmerTest::as_lmerModLmerTest}, so for computationally intensive model 92 | #' fits it can make sense to use \code{lme4::lmer} rather than \code{lmerTest::lmer} 93 | #' if computational time is an issue and summary tables and anova tables will 94 | #' not be needed. 95 | #' 96 | #' @author Alexandra Kuznetsova, Per Bruun Brockhoff, Rune Haubo Bojesen Christensen 97 | #' 98 | #' @references 99 | #' 100 | #' Alexandra Kuznetsova, Per B. Brockhoff and Rune H. B. Christensen (2017) 101 | #' lmerTest Package: Tests in Linear Mixed Effects Models. 102 | #' \emph{Journal of Statistical Software}, 82(13), 1--26. doi:10.18637/jss.v082.i13 103 | #' 104 | #' 105 | #' @docType package 106 | #' @name lmerTest-package 107 | #' @aliases lmerTest 108 | #' 109 | #' @examples 110 | #' 111 | #' ## load lmerTest package 112 | #' library(lmerTest) 113 | #' 114 | #' ## Fit linear mixed model to the ham data: 115 | #' fm <- lmer(Informed.liking ~ Gender + Information * Product + (1 | Consumer) + 116 | #' (1 | Consumer:Product), data=ham) 117 | #' 118 | #' ## Summary including coefficient table with p-values for t-statistics using 119 | #' ## Satterthwaite's method for denominator degrees of freedom: 120 | #' summary(fm) 121 | #' 122 | #' ## Type III anova table with p-values for F-tests based on Satterthwaite's 123 | #' ## method: 124 | #' (aov <- anova(fm)) 125 | #' 126 | #' ## Inspect the contrast matrix for the Type III test of Product: 127 | #' show_tests(aov, fractions = TRUE)$Product 128 | #' 129 | #' ## Choose type II anova table with Kenward-Roger method for the F-test: 130 | #' \dontrun{ 131 | #' if(requireNamespace("pbkrtest", quietly = TRUE)) 132 | #' anova(fm, type=2, ddf="Kenward-Roger") 133 | #' } 134 | #' 135 | #' ## Anova-like table of random-effect terms using likelihood ratio tests: 136 | #' ranova(fm) 137 | #' 138 | #' ## F-tests of 'single term deletions' for all marginal terms: 139 | #' drop1(fm) 140 | #' 141 | #' ## Least-Square means and pairwise differences: 142 | #' (lsm <- ls_means(fm)) 143 | #' ls_means(fm, which = "Product", pairwise = TRUE) 144 | #' 145 | #' ## ls_means also have plot and as.data.frame methods: 146 | #' \dontrun{ 147 | #' plot(lsm, which=c("Product", "Information")) 148 | #' as.data.frame(lsm) 149 | #' ## Inspect the LS-means contrasts: 150 | #' show_tests(lsm, fractions=TRUE)$Product 151 | #' } 152 | #' 153 | #' ## Contrast test (contest) using a custom contrast: 154 | #' ## Here we make the 2-df joint test of the main effects of Gender and Information 155 | #' (L <- diag(length(fixef(fm)))[2:3, ]) 156 | #' contest(fm, L = L) 157 | #' 158 | #' ## backward elimination of non-significant effects: 159 | #' step_result <- step(fm) 160 | #' 161 | #' ## Elimination tables for random- and fixed-effect terms: 162 | #' step_result 163 | #' 164 | #' # Extract the model that step found: 165 | #' final_model <- get_model(step_result) 166 | #' 167 | NULL 168 | -------------------------------------------------------------------------------- /R/lmer_summary.R: -------------------------------------------------------------------------------- 1 | ############################################################################# 2 | # Copyright (c) 2013-2020 Alexandra Kuznetsova, Per Bruun Brockhoff, and 3 | # Rune Haubo Bojesen Christensen 4 | # 5 | # This file is part of the lmerTest package for R (*lmerTest*) 6 | # 7 | # *lmerTest* is free software: you can redistribute it and/or modify 8 | # it under the terms of the GNU General Public License as published by 9 | # the Free Software Foundation, either version 2 of the License, or 10 | # (at your option) any later version. 11 | # 12 | # *lmerTest* is distributed in the hope that it will be useful, 13 | # but WITHOUT ANY WARRANTY; without even the implied warranty of 14 | # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 15 | # GNU General Public License for more details. 16 | # 17 | # A copy of the GNU General Public License is available at 18 | # and/or 19 | # . 20 | ############################################################################# 21 | # 22 | # lmer_summary.R - summary method for lmerModLmerTest objects 23 | 24 | # ------- Contents: -------- 25 | # 26 | # summary.lmerModLmerTest 27 | # 28 | # --- utility functions: --- 29 | # 30 | # get_coefmat 31 | # 32 | 33 | #' @include lmer.R 34 | NULL 35 | 36 | ############################################## 37 | ######## summary method for lmerModLmerTest 38 | ############################################## 39 | #' Summary Method for Linear Mixed Models 40 | #' 41 | #' Summaries of Linear Mixed Models with coefficient tables including t-tests 42 | #' and p-values using Satterthwaites's or Kenward-Roger's methods for 43 | #' degrees-of-freedom and t-statistics. 44 | #' 45 | #' The returned object is of class 46 | #' \code{c("summary.lmerModLmerTest", "summary.merMod")} utilizing \code{print}, 47 | #' \code{coef} and other methods defined for \code{summary.merMod} objects. 48 | #' The \code{"Kenward-Roger"} method use methods from the \pkg{pbkrtest} package internally 49 | #' to compute t-statistics and associated degrees-of-freedom. 50 | #' 51 | #' @param object an lmerModLmerTest object. 52 | #' @param ddf the method for computing the degrees of freedom and 53 | #' t-statistics. \code{ddf="Satterthwaite"} (default) uses Satterthwaite's method; 54 | #' \code{ddf="Kenward-Roger"} uses Kenward-Roger's method, 55 | #' \code{ddf = "lme4"} returns the lme4-summary i.e., using the summary 56 | #' method for \code{lmerMod} objects as defined in the \pkg{lme4}-package and 57 | #' ignores the \code{type} argument. Partial matching is allowed. 58 | #' @param ... additional arguments passed on to \code{lme4::summary.merMod} 59 | #' 60 | #' @return A summary object with a coefficient table (a \code{matrix}) including 61 | #' t-values and p-values. The coefficient table can be extracted with 62 | #' \code{coef(summary())}. 63 | #' 64 | #' @seealso \code{\link{contest1D}} for one degree-of-freedom contrast tests 65 | #' and \code{\link[pbkrtest]{KRmodcomp}} for Kenward-Roger F-tests. 66 | #' @author Rune Haubo B. Christensen and Alexandra Kuznetsova 67 | #' @export 68 | #' @importFrom methods as signature 69 | #' 70 | #' @examples 71 | #' 72 | #' # Fit example model: 73 | #' data("sleepstudy", package="lme4") 74 | #' fm <- lmer(Reaction ~ Days + (1|Subject) + (0+Days|Subject), sleepstudy) 75 | #' 76 | #' # Get model summary: 77 | #' summary(fm) # Satterthwaite df and t-tests 78 | #' 79 | #' # Extract coefficient table: 80 | #' coef(summary(fm)) 81 | #' 82 | #' # Use the Kenward-Roger method 83 | #' if(requireNamespace("pbkrtest", quietly = TRUE)) 84 | #' summary(fm, ddf="Kenward-Roger") 85 | #' 86 | #' # The lme4-summary table: 87 | #' summary(fm, ddf="lme4") # same as summary(as(fm, "lmerMod")) 88 | #' 89 | #' \dontshow{ 90 | #' # Check that summaries are as expected: 91 | #' summ_fm <- coef(summary(fm)) 92 | #' summ_fm_lme4 <- coef(summary(fm, ddf="lme4")) 93 | #' stopifnot( 94 | #' all(colnames(summ_fm) == c("Estimate", "Std. Error", "df", "t value", "Pr(>|t|)")), 95 | #' all(colnames(summ_fm_lme4) == c("Estimate", "Std. Error", "t value")), 96 | #' all(!(is.na(summ_fm))), 97 | #' all(!(is.na(summ_fm_lme4))) 98 | #' ) 99 | #' if(requireNamespace("pbkrtest", quietly = TRUE) && getRversion() >= "3.3.3") { 100 | #' summ_fm_kr <- coef(summary(fm, ddf="Kenward-Roger")) 101 | #' stopifnot( 102 | #' all(colnames(summ_fm_kr) == c("Estimate", "Std. Error", "df", "t value", "Pr(>|t|)")), 103 | #' all(!(is.na(summ_fm_kr))) 104 | #' ) 105 | #' } 106 | #' } 107 | summary.lmerModLmerTest <- function(object, ..., 108 | ddf=c("Satterthwaite", "Kenward-Roger", "lme4")) { 109 | ddf <- match.arg(ddf) 110 | if(!inherits(object, "lmerModLmerTest") && !inherits(object, "lmerMod")) { 111 | stop("Cannot compute summary for objects of class: ", 112 | paste(class(object), collapse = ", ")) 113 | } 114 | if(!inherits(object, "lmerModLmerTest") && inherits(object, "lmerMod")) { 115 | message("Coercing object to class 'lmerModLmerTest'") 116 | object <- as_lmerModLmerTest(object) 117 | if(!inherits(object, "lmerModLmerTest")) { 118 | warning("Failed to coerce object to class 'lmerModLmerTest'") 119 | return(summary(object)) 120 | } 121 | } 122 | summ <- summary(as(object, "lmerMod"), ...) 123 | if(ddf == "lme4") return(summ) 124 | summ$coefficients <- get_coefmat(object, ddf=ddf) 125 | ddf_nm <- switch(ddf, "Satterthwaite" = "Satterthwaite's", 126 | "Kenward-Roger" = "Kenward-Roger's") 127 | summ$objClass <- class(object) # Used by lme4:::print.summary.lmerMod 128 | summ$methTitle <- paste0(summ$methTitle, ". t-tests use ", ddf_nm, " method") 129 | class(summ) <- c("summary.lmerModLmerTest", class(summ)) 130 | summ 131 | } 132 | 133 | 134 | ############################################## 135 | ######## get_coefmat 136 | ############################################## 137 | #' @importFrom lme4 fixef 138 | get_coefmat <- function(model, ddf=c("Satterthwaite", "Kenward-Roger")) { 139 | ddf <- match.arg(ddf) 140 | p <- length(fixef(model)) 141 | if(p < 1) 142 | return(as.matrix(contest1D(model, numeric(0L), ddf=ddf))) 143 | Lmat <- diag(p) 144 | tab <- rbindall(lapply(1:p, function(i) contest1D(model, Lmat[i, ], ddf=ddf))) 145 | rownames(tab) <- names(fixef(model)) 146 | as.matrix(tab) 147 | } 148 | -------------------------------------------------------------------------------- /R/terms_utils.R: -------------------------------------------------------------------------------- 1 | ############################################################################# 2 | # Copyright (c) 2013-2020 Alexandra Kuznetsova, Per Bruun Brockhoff, and 3 | # Rune Haubo Bojesen Christensen 4 | # 5 | # This file is part of the lmerTest package for R (*lmerTest*) 6 | # 7 | # *lmerTest* is free software: you can redistribute it and/or modify 8 | # it under the terms of the GNU General Public License as published by 9 | # the Free Software Foundation, either version 2 of the License, or 10 | # (at your option) any later version. 11 | # 12 | # *lmerTest* is distributed in the hope that it will be useful, 13 | # but WITHOUT ANY WARRANTY; without even the implied warranty of 14 | # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 15 | # GNU General Public License for more details. 16 | # 17 | # A copy of the GNU General Public License is available at 18 | # and/or 19 | # . 20 | ############################################################################# 21 | # 22 | # terms_utils.R - utilities for computing on terms objects and friends 23 | 24 | # ------- Contents: -------- 25 | # 26 | # --- utility functions: --- 27 | # 28 | # term2colX 29 | # need_yates 30 | # no_yates 31 | # numeric_terms 32 | # get_model_matrix 33 | # get_contrast_coding 34 | # get_min_data 35 | # get_var_list 36 | # get_fac_list 37 | # get_num_list 38 | # get_pairs 39 | # get_trts 40 | # 41 | 42 | ############################################## 43 | ######## term2colX() 44 | ############################################## 45 | term2colX <- function(terms, X) { 46 | # Compute map from terms to columns in X using the assign attribute of X. 47 | # Returns a list with one element for each term containing indices of columns 48 | # in X belonging to that term. 49 | if(is.null(asgn <- attr(X, "assign"))) 50 | stop("Invalid design matrix:", 51 | "design matrix 'X' should have a non-null 'assign' attribute", 52 | call. = FALSE) 53 | term_names <- attr(terms, "term.labels") 54 | has_intercept <- attr(terms, "intercept") > 0 55 | col_terms <- if(has_intercept) c("(Intercept)", term_names)[asgn + 1] else 56 | term_names[asgn[asgn > 0]] 57 | if(!length(col_terms) == ncol(X)) # should never happen. 58 | stop("An error happended when mapping terms to columns of X") 59 | # get names of terms (including aliased terms) 60 | nm <- union(unique(col_terms), term_names) 61 | res <- lapply(setNames(as.list(nm), nm), function(x) numeric(0L)) 62 | map <- split(seq_along(col_terms), col_terms) 63 | res[names(map)] <- map 64 | res[nm] # order appropriately 65 | } 66 | 67 | ############################################## 68 | ######## need_yates() 69 | ############################################## 70 | need_yates <- function(model) { 71 | ## Do not need yates for: 72 | ## - continuous variables 73 | ## - factors that are not contained in other factors 74 | ## Need yates for all other terms, i.e. terms which are: 75 | ## - contained in other terms, AND 76 | ## - which are not numeric/continuous 77 | term_names <- attr(terms(model), "term.labels") 78 | cont <- containment(model) 79 | is_contained <- names(cont[sapply(cont, function(x) length(x) > 0)]) 80 | nmt <- numeric_terms(model) 81 | num_terms <- names(nmt[nmt]) 82 | term_names[!term_names %in% num_terms & 83 | term_names %in% is_contained] 84 | } 85 | 86 | ############################################## 87 | ######## no_yates() 88 | ############################################## 89 | no_yates <- function(model) { 90 | setdiff(attr(terms(model), "term.labels"), need_yates(model)) 91 | } 92 | 93 | ############################################## 94 | ######## numeric_terms() 95 | ############################################## 96 | #' @importFrom stats delete.response terms 97 | numeric_terms <- function(model) { 98 | ## Determines for all terms (not just all variables) if the 'dataClass' 99 | ## is numeric 100 | ## (interactions involving one or more numerics variables are numeric). 101 | Terms <- delete.response(terms(model)) 102 | all_vars <- all.vars(attr(Terms, "variables")) 103 | data_classes <- attr(terms(model, fixed.only=FALSE), "dataClasses") 104 | var_class <- data_classes[names(data_classes) %in% all_vars] 105 | factor_vars <- names(var_class[var_class %in% c("factor", "ordered")]) 106 | num_vars <- setdiff(all_vars, factor_vars) 107 | 108 | term_names <- attr(terms(model), "term.labels") 109 | # term_names <- setNames(as.list(term_names), term_names) 110 | sapply(term_names, function(term) { 111 | vars <- unlist(strsplit(term, ":")) 112 | any(vars %in% num_vars) 113 | }) 114 | } 115 | 116 | ############################################## 117 | ######## get_model_matrix() 118 | ############################################## 119 | #' Extract or remake model matrix from model 120 | #' 121 | #' Extract or remake model matrix from model and potentially change the 122 | #' contrast coding 123 | #' 124 | #' @param model an \code{lm} or \code{lmerMod} model object. 125 | #' @param type extract or remake model matrix? 126 | #' @param contrasts contrasts settings. These may be restored to those in the 127 | #' model or they may be changed. If a length one character vector (e.g. 128 | #' \code{"contr.SAS"}) this is applied to all factors in the model, but it can 129 | #' also be a list naming factors for which the contrasts should be set as specified. 130 | #' 131 | #' @return the model (or 'design') matrix. 132 | #' @keywords internal 133 | #' @author Rune Haubo B Christensen 134 | get_model_matrix <- function(model, type=c("extract", "remake"), 135 | contrasts="restore") { 136 | type <- match.arg(type) 137 | stopifnot(inherits(model, "lm") || inherits(model, "lmerMod")) 138 | 139 | if(type == "extract") return(model.matrix(model)) 140 | # Set appropriate contrasts: 141 | Contrasts <- get_contrast_coding(model, contrasts=contrasts) 142 | model.matrix(terms(model), data=model.frame(model), 143 | contrasts.arg = Contrasts) 144 | } 145 | 146 | ############################################## 147 | ######## get_contrast_coding() 148 | ############################################## 149 | get_contrast_coding <- function(model, contrasts="restore") { 150 | # Compute a list of contrasts for all factors in model 151 | Contrasts <- contrasts 152 | if(length(contrasts) == 1 && is.character(contrasts) && 153 | contrasts == "restore") { 154 | Contrasts <- attr(model.matrix(model), "contrasts") 155 | } else if(length(contrasts) == 1 && is.character(contrasts) && 156 | contrasts != "restore") { 157 | Contrasts <- .getXlevels(terms(model), model.frame(model)) 158 | Contrasts[] <- contrasts 159 | Contrasts 160 | } 161 | Contrasts 162 | } 163 | 164 | 165 | get_min_data <- function(model, FUN=mean) 166 | # Get a minimum complete model.frame based on the variables in the model 167 | do.call(expand.grid, get_var_list(model, FUN=FUN)) 168 | 169 | get_var_list <- function(model, FUN=mean) 170 | # Extract a named list of variables in the model containing the levels of 171 | # factors and the mean value of numeric variables 172 | c(get_fac_list(model), get_num_list(model, FUN=FUN)) 173 | 174 | #' @importFrom stats .getXlevels 175 | get_fac_list <- function(model) { 176 | # Extract a named list of factor levels for each factor in the model 177 | res <- .getXlevels(Terms=terms(model), m=model.frame(model)) 178 | if(is.null(res)) list() else res 179 | } 180 | 181 | get_num_list <- function(model, FUN=mean) { # FUN=function(x) mean(x, na.rm=TRUE)) { 182 | # Extract named list of mean/FUN values of numeric variables in model 183 | Terms <- terms(model) 184 | mf <- model.frame(model) 185 | xvars <- sapply(attr(Terms, "variables"), deparse2)[-1L] 186 | if((yvar <- attr(Terms, "response")) > 0) 187 | xvars <- xvars[-yvar] 188 | if(!length(xvars)) return(list()) 189 | xlev <- lapply(mf[xvars], function(x) { 190 | if (is.numeric(x)) FUN(x) else NULL 191 | }) 192 | res <- xlev[!vapply(xlev, is.null, NA)] 193 | if(is.null(res)) list() else res 194 | } 195 | 196 | #' @importFrom utils combn 197 | get_pairs <- function(levs) { 198 | stopifnot(is.character(levs), length(levs) > 1) 199 | combs <- combn(seq_along(levs), 2) 200 | ind <- seq_len(ncombs <- ncol(combs)) 201 | A <- as.data.frame(array(0, dim=c(length(levs), ncombs))) 202 | dimnames(A) <- list(levs, paste(levs[combs[1, ]], levs[combs[2, ]], sep=" - ")) 203 | A[cbind(combs[1, ], ind)] <- 1 204 | A[cbind(combs[2, ], ind)] <- -1 205 | A 206 | } 207 | 208 | get_trts <- function(levs) { 209 | nlevs <- length(levs) 210 | ans <- t(cbind(-1, diag(nlevs - 1))) 211 | rownames(ans) <- levs 212 | colnames(ans) <- paste(levs[-1], levs[1], sep=" - ") 213 | ans 214 | } 215 | 216 | # get_trts(letters[1:5]) 217 | # get_pairs(letters[1:5]) 218 | 219 | -------------------------------------------------------------------------------- /R/utils.R: -------------------------------------------------------------------------------- 1 | ############################################################################# 2 | # Copyright (c) 2013-2020 Alexandra Kuznetsova, Per Bruun Brockhoff, and 3 | # Rune Haubo Bojesen Christensen 4 | # 5 | # This file is part of the lmerTest package for R (*lmerTest*) 6 | # 7 | # *lmerTest* is free software: you can redistribute it and/or modify 8 | # it under the terms of the GNU General Public License as published by 9 | # the Free Software Foundation, either version 2 of the License, or 10 | # (at your option) any later version. 11 | # 12 | # *lmerTest* is distributed in the hope that it will be useful, 13 | # but WITHOUT ANY WARRANTY; without even the implied warranty of 14 | # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 15 | # GNU General Public License for more details. 16 | # 17 | # A copy of the GNU General Public License is available at 18 | # and/or 19 | # . 20 | ############################################################################# 21 | # 22 | # utils.R - Utility functions 23 | 24 | # ------- Contents: -------- 25 | # 26 | # --- utility functions: --- 27 | # 28 | # qform 29 | # rbindall 30 | # cond 31 | # safeDeparse, deparse2 32 | # waldCI 33 | # 34 | 35 | ############################################## 36 | ######## qform 37 | ############################################## 38 | 39 | #' Compute Quadratic Form 40 | #' 41 | #' Efficiently computes \eqn{x' A x} - or in R-notation: 42 | #' 43 | #' Length of \code{x} should equal the number of rows and columns of \code{A}. 44 | #' 45 | #' @param x a numeric vector 46 | #' @param A a symmetric numeric matrix 47 | #' 48 | #' @return a numerical scalar 49 | #' @keywords internal 50 | qform <- function(x, A) { 51 | sum(x * (A %*% x)) # quadratic form: x'Ax 52 | } 53 | 54 | ############################################## 55 | ######## rbindall 56 | ############################################## 57 | 58 | #' \code{rbind} Multiple Objects 59 | #' 60 | #' @param ... objects to be \code{rbind}'ed - typically matrices or vectors 61 | #' 62 | #' @keywords internal 63 | rbindall <- function(...) do.call(rbind, ...) 64 | 65 | cbindall <- function(...) do.call(cbind, ...) 66 | 67 | ############################################## 68 | ######## cond 69 | ############################################## 70 | cond <- function(X) with(eigen(X, only.values=TRUE), max(values) / min(values)) 71 | 72 | ############################################## 73 | ######## safeDeparse 74 | ############################################## 75 | safeDeparse <- function(expr, width.cutoff=500L, backtick = mode(expr) %in% 76 | c("call", "expression", "(", "function"), 77 | control = c("keepInteger","showAttributes", "keepNA"), 78 | nlines = -1L) { 79 | deparse(expr=expr, width.cutoff=width.cutoff, backtick=backtick, 80 | control=control, nlines=nlines) 81 | } 82 | 83 | deparse2 <- function(x) paste(safeDeparse(x), collapse = " ") 84 | 85 | ############################################## 86 | ######## waldCI 87 | ############################################## 88 | #' @importFrom stats qt 89 | waldCI <- function(estimate, se, df=Inf, level=0.95) { 90 | stopifnot(length(level) == 1, 91 | is.numeric(level), 92 | level > 0, level < 1) 93 | # all(se > 0)) 94 | alpha <- (1 - level)/2 95 | fac <- qt(alpha, df=df, lower.tail = FALSE) 96 | res <- cbind(lower = estimate - se * fac, 97 | upper = estimate + se * fac) 98 | if(!is.null(names(estimate))) rownames(res) <- names(estimate) 99 | res 100 | } 101 | 102 | # waldCI(setNames(1, "est"), .2) 103 | 104 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # lmerTest - Tests in Linear Mixed Effects Models 2 | 3 | This is the repo for the _new_ **lmerTest** package, the old package is available [here](https://github.com/runehaubo/lmerTest). 4 | 5 | [![Build Status](https://travis-ci.org/runehaubo/lmerTestR.svg?branch=master)](https://travis-ci.org/runehaubo/lmerTestR) 6 | [![cran version](http://www.r-pkg.org/badges/version/lmerTest)](https://cran.r-project.org/package=lmerTest) 7 | [![downloads](https://cranlogs.r-pkg.org/badges/lmerTest)](https://cran.r-project.org/package=lmerTest) 8 | [![total downloads](http://cranlogs.r-pkg.org/badges/grand-total/lmerTest)](http://cranlogs.r-pkg.org/badges/grand-total/lmerTest) 9 | [![Research software impact](http://depsy.org/api/package/cran/lmerTest/badge.svg)](http://depsy.org/package/r/lmerTest) 10 | 11 | ## Main features 12 | 13 | The **lmerTest** package provides _p_-values in type I, II or III `anova` and `summary` 14 | tables for linear mixed models (`lmer` model fits cf. **lme4**) via Satterthwaite's degrees of freedom method; a Kenward-Roger method is also available via the **pbkrtest** 15 | package. Model selection and assessment methods include `step`, `drop1`, anova-like 16 | tables for random effects (`ranova`), least-square means (LS-means; `ls_means`) 17 | and tests of linear contrasts of fixed effects (`contest`). 18 | 19 | ## Citation 20 | 21 | To cite **lmerTest** in publications use: 22 | 23 | Kuznetsova A., Brockhoff P.B. and Christensen R.H.B. (2017). "lmerTest Package: Tests in Linear Mixed Effects Models." _Journal of Statistical Software_, 82(13), pp. 1–26. doi: 10.18637/jss.v082.i13. 24 | 25 | Corresponding BibTeX entry: 26 | 27 | @Article{, 28 | title = {{lmerTest} Package: Tests in Linear Mixed Effects Models}, 29 | author = {Alexandra Kuznetsova and Per B. Brockhoff and Rune H. B. 30 | Christensen}, 31 | journal = {Journal of Statistical Software}, 32 | year = {2017}, 33 | volume = {82}, 34 | number = {13}, 35 | pages = {1--26}, 36 | doi = {10.18637/jss.v082.i13}, 37 | } 38 | 39 | ## Discovered a bug? 40 | 41 | Please raise a new issue! Preferably add code that illustrates the problem using one of the datasets from **lmerTest**. 42 | 43 | ## Installation 44 | 45 | Basically there are two options for installing **lmerTest**: 46 | 47 | 1. Released (stable version) from CRAN: in **R** run `install.packages("lmerTest")`. 48 | 2. Development version from GitHub: First load the **devtools** package (and install it if you do not have it) and install the default (master) branch: 49 | ``` 50 | library("devtools") 51 | install_github("runehaubo/lmerTestR") 52 | ``` 53 | If you haven't already installed a previous version of **lmerTest** you need to also install dependencies (other packages that **lmerTest** depends on and requires you to install to function properly). We recommend that you install **lmerTest** from CRAN (using `install.packages("lmerTest")`) before installing from GitHub as described above. 54 | 55 | An alternative is to use 56 | ``` 57 | library("devtools") 58 | install_github("runehaubo/lmerTestR", dependencies=TRUE) 59 | ``` 60 | but that requires you to install all dependent packages from source (which only works if you have the correct compilers installed and set up correctly); installing the pre-compiled packages from CRAN is usually easier. 61 | 62 | 63 | 64 | 65 | -------------------------------------------------------------------------------- /data/TVbo.rda: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/runehaubo/lmerTestR/35dc5885205d709cdc395b369b08ca2b7273cb78/data/TVbo.rda -------------------------------------------------------------------------------- /data/carrots.rda: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/runehaubo/lmerTestR/35dc5885205d709cdc395b369b08ca2b7273cb78/data/carrots.rda -------------------------------------------------------------------------------- /data/ham.rda: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/runehaubo/lmerTestR/35dc5885205d709cdc395b369b08ca2b7273cb78/data/ham.rda -------------------------------------------------------------------------------- /inst/CITATION: -------------------------------------------------------------------------------- 1 | bibentry(bibtype = "Article", 2 | title = "{lmerTest} Package: Tests in Linear Mixed Effects Models", 3 | author = c(person(given = "Alexandra", 4 | family = "Kuznetsova", 5 | email = "alku@dtu.dk"), 6 | person(given = c("Per", "B."), 7 | family = "Brockhoff", 8 | email = "perbb@dtu.dk"), 9 | person(given = c("Rune", "H.", "B."), 10 | family = "Christensen", 11 | email = "Rune@ChristensenStatistics.dk")), 12 | journal = "Journal of Statistical Software", 13 | year = "2017", 14 | volume = "82", 15 | number = "13", 16 | pages = "1--26", 17 | doi = "10.18637/jss.v082.i13", 18 | 19 | header = "To cite lmerTest in publications use:" 20 | ) 21 | 22 | -------------------------------------------------------------------------------- /inst/testdata/legacy_fits.RData: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/runehaubo/lmerTestR/35dc5885205d709cdc395b369b08ca2b7273cb78/inst/testdata/legacy_fits.RData -------------------------------------------------------------------------------- /inst/testdata/potdata.RData: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/runehaubo/lmerTestR/35dc5885205d709cdc395b369b08ca2b7273cb78/inst/testdata/potdata.RData -------------------------------------------------------------------------------- /inst/testdata/test_paper_objects.RData: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/runehaubo/lmerTestR/35dc5885205d709cdc395b369b08ca2b7273cb78/inst/testdata/test_paper_objects.RData -------------------------------------------------------------------------------- /man/TVbo.Rd: -------------------------------------------------------------------------------- 1 | % Generated by roxygen2: do not edit by hand 2 | % Please edit documentation in R/data_documentation.R 3 | \docType{data} 4 | \name{TVbo} 5 | \alias{TVbo} 6 | \title{Sensory Assesment of B&O TVs} 7 | \format{ 8 | \describe{ 9 | \item{Assessor}{factor with 8 levels assessors.} 10 | \item{TVset}{product factor with 3 levels.} 11 | \item{Picture}{product factor with 4 levels.} 12 | } 13 | In addition the following 15 numeric (response) variables are the 14 | characteristics on which the TV sets (products) are assessed: 15 | 16 | Coloursaturation, Colourbalance, Noise, Depth, Sharpness, Lightlevel, 17 | Contrast, Sharpnessofmovement, Flickeringstationary, Flickeringmovement, 18 | Distortion, Dimglasseffect, Cutting, Flossyedges, Elasticeffect. 19 | } 20 | \usage{ 21 | data(TVbo) 22 | } 23 | \description{ 24 | The TVbo dataset has kindly been made available by the Danish high-end 25 | consumer electronics company 26 | \href{https://www.bang-olufsen.com}{Bang & Olufsen}. 27 | The main purpose was to assess 12 different TV sets (products) specified by 28 | the two attributes Picture and TVset. 29 | 15 different response variables (characteristics of the 30 | product) were assessed by a trained panel with 8 assessors. 31 | } 32 | \examples{ 33 | 34 | fm <- lmer(Coloursaturation ~ TVset + Picture + (1|Assessor:TVset) + 35 | (1|Assessor), data=TVbo) 36 | ranova(fm) 37 | anova(fm) 38 | 39 | } 40 | \keyword{datasets} 41 | -------------------------------------------------------------------------------- /man/anova.lmerModLmerTest.Rd: -------------------------------------------------------------------------------- 1 | % Generated by roxygen2: do not edit by hand 2 | % Please edit documentation in R/lmer_anova.R 3 | \name{anova.lmerModLmerTest} 4 | \alias{anova.lmerModLmerTest} 5 | \title{ANOVA Tables for Linear Mixed Models} 6 | \usage{ 7 | \method{anova}{lmerModLmerTest}( 8 | object, 9 | ..., 10 | type = c("III", "II", "I", "3", "2", "1"), 11 | ddf = c("Satterthwaite", "Kenward-Roger", "lme4") 12 | ) 13 | } 14 | \arguments{ 15 | \item{object}{an \code{lmerModLmerTest} object; the result of \code{lmer()} 16 | after loading the \pkg{lmerTest}-package.} 17 | 18 | \item{...}{potentially additional \code{lmer} or \code{lm} model objects for 19 | comparison of models in which case \code{type} and \code{ddf} arguments are 20 | ignored.} 21 | 22 | \item{type}{the type of ANOVA table requested (using SAS terminology) 23 | with Type I being the familiar sequential ANOVA table.} 24 | 25 | \item{ddf}{the method for computing the denominator degrees of freedom and 26 | F-statistics. \code{ddf="Satterthwaite"} (default) uses Satterthwaite's method; 27 | \code{ddf="Kenward-Roger"} uses Kenward-Roger's method, 28 | \code{ddf = "lme4"} returns the lme4-anova table, i.e., using the anova 29 | method for \code{lmerMod} objects as defined in the \pkg{lme4}-package and 30 | ignores the \code{type} argument. Partial matching is allowed.} 31 | } 32 | \value{ 33 | an ANOVA table 34 | } 35 | \description{ 36 | ANOVA table with F-tests and p-values using Satterthwaite's or 37 | Kenward-Roger's method for denominator degrees-of-freedom and F-statistic. 38 | Models should be fitted with 39 | \code{\link{lmer}} from the \pkg{lmerTest}-package. 40 | } 41 | \details{ 42 | The \code{"Kenward-Roger"} method calls \code{pbkrtest::KRmodcomp} internally and 43 | reports scaled F-statistics and associated denominator degrees-of-freedom. 44 | } 45 | \examples{ 46 | 47 | data("sleepstudy", package="lme4") 48 | m <- lmer(Reaction ~ Days + (Days | Subject), sleepstudy) 49 | anova(m) # with p-values from F-tests using Satterthwaite's denominator df 50 | anova(m, ddf="lme4") # no p-values 51 | 52 | # Use the Kenward-Roger method 53 | if(requireNamespace("pbkrtest", quietly = TRUE)) 54 | anova(m, ddf="Kenward-Roger") 55 | 56 | \dontshow{ 57 | an1 <- anova(m) # with p-values from F-tests using Satterthwaite's denominator df 58 | an2 <- anova(m, ddf="lme4") 59 | stopifnot( 60 | all(colnames(an1) == c("Sum Sq", "Mean Sq", "NumDF", "DenDF", "F value", "Pr(>F)")), 61 | !"Pr(>F)" \%in\% colnames(an2), 62 | all(!is.na(an1)), 63 | all(!is.na(an2)) 64 | ) 65 | } 66 | } 67 | \seealso{ 68 | \code{\link{contestMD}} for multi degree-of-freedom contrast tests 69 | and \code{\link[pbkrtest]{KRmodcomp}} for the \code{"Kenward-Roger"} method. 70 | } 71 | \author{ 72 | Rune Haubo B. Christensen and Alexandra Kuznetsova 73 | } 74 | -------------------------------------------------------------------------------- /man/as.data.frame.ls_means.Rd: -------------------------------------------------------------------------------- 1 | % Generated by roxygen2: do not edit by hand 2 | % Please edit documentation in R/ls_means.R 3 | \name{as.data.frame.ls_means} 4 | \alias{as.data.frame.ls_means} 5 | \title{Coerce \code{ls_means} Objects to \code{data.frame}s} 6 | \usage{ 7 | \method{as.data.frame}{ls_means}(x, ..., add_levels = TRUE) 8 | } 9 | \arguments{ 10 | \item{x}{an \code{\link{ls_means}} object.} 11 | 12 | \item{...}{currently not used.} 13 | 14 | \item{add_levels}{add \code{term} and \code{levels} columns to returned 15 | \code{data.frame}?} 16 | } 17 | \description{ 18 | Coerce \code{ls_means} Objects to \code{data.frame}s 19 | } 20 | \examples{ 21 | 22 | # Fit example model: 23 | data("cake", package="lme4") 24 | cake$Temp <- factor(cake$temperature, ordered = FALSE) 25 | model <- lmer(angle ~ recipe + Temp + (1|recipe:replicate), cake) 26 | 27 | # Extract LS-means: 28 | head(lsm <- ls_means(model)) 29 | 30 | # Coerce LS-means objects to data.frames: 31 | head(as.data.frame(lsm)) 32 | head(as.data.frame(lsm, add_levels=FALSE)) 33 | 34 | } 35 | \seealso{ 36 | \code{\link{ls_means.lmerModLmerTest}} 37 | } 38 | \author{ 39 | Rune Haubo B. Christensen 40 | } 41 | \keyword{internal} 42 | -------------------------------------------------------------------------------- /man/as_lmerModLmerTest.Rd: -------------------------------------------------------------------------------- 1 | % Generated by roxygen2: do not edit by hand 2 | % Please edit documentation in R/lmer.R 3 | \name{as_lmerModLmerTest} 4 | \alias{as_lmerModLmerTest} 5 | \title{Coerce lmerMod Objects to lmerModLmerTest} 6 | \usage{ 7 | as_lmerModLmerTest(model, tol = 1e-08) 8 | } 9 | \arguments{ 10 | \item{model}{and lmer model-object (of class 'lmerMod') -- the result of a 11 | call to \code{lme4::lmer()}} 12 | 13 | \item{tol}{tolerance for determining of eigenvalues are negative, zero or 14 | positive} 15 | } 16 | \value{ 17 | an object of class \code{'lmerModLmerTest'} which sets the following 18 | slots: 19 | \item{vcov_varpar}{the asymptotic covariance matrix of the variance parameters 20 | (theta, sigma).} 21 | \item{Jac_list}{list of Jacobian matrices; gradients of vcov(beta) with 22 | respect to the variance parameters.} 23 | \item{vcov_beta}{the asymptotic covariance matrix of the fixed-effect 24 | regression parameters (beta; vcov(beta)).} 25 | \item{sigma}{the residual standard deviation.} 26 | } 27 | \description{ 28 | Coercing an lme4::lmer model-object (of class 'lmerMod') to a model-object 29 | of class 'lmerModLmerTest' involves computing the covariance 30 | matrix of the variance parameters and the gradient (Jacobian) of cov(beta) 31 | with respect to the variance parameters. 32 | } 33 | \examples{ 34 | m <- lme4::lmer(Reaction ~ Days + (Days | Subject), sleepstudy) 35 | bm <- as_lmerModLmerTest(m) 36 | slotNames(bm) 37 | 38 | } 39 | \seealso{ 40 | the class definition in \code{\link{lmerModLmerTest}}) and 41 | \code{\link{lmer}} 42 | } 43 | \author{ 44 | Rune Haubo B. Christensen 45 | } 46 | -------------------------------------------------------------------------------- /man/carrots.Rd: -------------------------------------------------------------------------------- 1 | % Generated by roxygen2: do not edit by hand 2 | % Please edit documentation in R/data_documentation.R 3 | \docType{data} 4 | \name{carrots} 5 | \alias{carrots} 6 | \title{Consumer Preference Mapping of Carrots} 7 | \format{ 8 | \describe{ 9 | \item{Consumer}{factor with 103 levels: numbering identifying consumers.} 10 | \item{Frequency}{factor with 5 levels; "How often do you eat carrots?" 11 | 1: once a week or more, 2: once 12 | every two weeks, 3: once every three weeks, 4: at least once month, 13 | 5: less than once a month.} 14 | \item{Gender}{factor with 2 levels. 1: male, 2:female.} 15 | \item{Age}{factor with 4 levels. 1: less than 25 years, 2: 26-40 years, 16 | 3: 41-60 years, 4 more than 61 years.} 17 | \item{Homesize}{factor with two levels. Number of persons in the household. 18 | 1: 1 or 2 persons, 2: 3 or more persons.} 19 | \item{Work}{factor with 7 levels. different types of employment. 20 | 1: unskilled worker(no education), 21 | 2: skilled worker(with education), 3: office worker, 4: housewife (or man), 22 | 5: independent 23 | businessman/ self-employment, 6: student, 7: retired} 24 | \item{Income}{factor with 4 levels. 1: <150000, 2: 150000-300000, 25 | 3: 300000-500000, 4: >500000} 26 | \item{Preference}{consumer score on a seven-point scale.} 27 | \item{Sweetness}{consumer score on a seven-point scale.} 28 | \item{Bitterness}{consumer score on a seven-point scale.} 29 | \item{Crispness}{consumer score on a seven-point scale.} 30 | \item{sens1}{first sensory variable derived from a PCA.} 31 | \item{sens2}{second sensory variable derived from a PCA.} 32 | \item{Product}{factor on 12 levels.} 33 | } 34 | } 35 | \source{ 36 | Per Bruun Brockhoff, The Royal Veterinary and Agricultural University, 37 | Denmark. 38 | } 39 | \usage{ 40 | data(carrots) 41 | } 42 | \description{ 43 | In a consumer study 103 consumers scored their preference of 12 danish 44 | carrot types on a scale from 1 to 7. Moreover the consumers scored the 45 | degree of sweetness, bitterness and crispiness in the products. 46 | } 47 | \details{ 48 | The carrots were harvested in autumn 1996 and tested in march 1997. In 49 | addition to the consumer survey, the carrot products were evaluated by 50 | a trained panel of tasters, the sensory panel, with respect to a 51 | number of sensory (taste, odour and texture) properties. Since usually 52 | a high number of (correlated) properties (variables) are used, in this 53 | case 14, it is a common procedure to use a few, often 2, combined 54 | variables that contain as much of the information in the sensory 55 | variables as possible. This is achieved by extracting the first two 56 | principal components in a principal components analysis (PCA) on the 57 | product-by-property panel average data matrix. In this data set the 58 | variables for the first two principal components are named 59 | (\code{sens1} and \code{sens2}). 60 | } 61 | \examples{ 62 | 63 | fm <- lmer(Preference ~ sens2 + Homesize + (1 + sens2 | Consumer), data=carrots) 64 | anova(fm) 65 | 66 | } 67 | \keyword{datasets} 68 | -------------------------------------------------------------------------------- /man/containment.Rd: -------------------------------------------------------------------------------- 1 | % Generated by roxygen2: do not edit by hand 2 | % Please edit documentation in R/contrast_utils.R 3 | \name{containment} 4 | \alias{containment} 5 | \title{Determine the Containment Structure for All Terms in a Model} 6 | \usage{ 7 | containment(object) 8 | } 9 | \arguments{ 10 | \item{object}{a model object, e.g. of class \code{lm} or \code{merMod}.} 11 | } 12 | \value{ 13 | a list with one element for each term in the model. Each element/term 14 | is a character vector of terms that the term is contained in. 15 | } 16 | \description{ 17 | See \code{\link{term_contain}} for details about containment. 18 | } 19 | \keyword{internal} 20 | -------------------------------------------------------------------------------- /man/contest.Rd: -------------------------------------------------------------------------------- 1 | % Generated by roxygen2: do not edit by hand 2 | % Please edit documentation in R/contest.R 3 | \name{contest} 4 | \alias{contest} 5 | \alias{contest1D} 6 | \alias{contestMD} 7 | \title{Generic Contrast Test Functions} 8 | \usage{ 9 | contest(model, L, ...) 10 | 11 | contest1D(model, L, ...) 12 | 13 | contestMD(model, L, ...) 14 | } 15 | \arguments{ 16 | \item{model}{a model object.} 17 | 18 | \item{L}{a contrast vector or matrix.} 19 | 20 | \item{...}{additional arguments passed to methods.} 21 | } 22 | \description{ 23 | Generic functions for tests contrasts. 24 | } 25 | \seealso{ 26 | contest methods for \code{\link{lmer}} objects: 27 | \code{\link[=contest.lmerModLmerTest]{contest}}, 28 | \code{\link[=contest1D.lmerModLmerTest]{contest1D}}, and 29 | \code{\link[=contestMD.lmerModLmerTest]{contestMD}}. 30 | } 31 | \author{ 32 | Rune Haubo B. Christensen 33 | } 34 | \keyword{internal} 35 | -------------------------------------------------------------------------------- /man/contest.lmerModLmerTest.Rd: -------------------------------------------------------------------------------- 1 | % Generated by roxygen2: do not edit by hand 2 | % Please edit documentation in R/contest.R 3 | \name{contest.lmerModLmerTest} 4 | \alias{contest.lmerModLmerTest} 5 | \alias{contest.lmerMod} 6 | \title{Test of Contrasts} 7 | \usage{ 8 | \method{contest}{lmerModLmerTest}( 9 | model, 10 | L, 11 | rhs = 0, 12 | joint = TRUE, 13 | collect = TRUE, 14 | confint = TRUE, 15 | level = 0.95, 16 | check_estimability = FALSE, 17 | ddf = c("Satterthwaite", "Kenward-Roger", "lme4"), 18 | ... 19 | ) 20 | 21 | \method{contest}{lmerMod}( 22 | model, 23 | L, 24 | rhs = 0, 25 | joint = TRUE, 26 | collect = TRUE, 27 | confint = TRUE, 28 | level = 0.95, 29 | check_estimability = FALSE, 30 | ddf = c("Satterthwaite", "Kenward-Roger", "lme4"), 31 | ... 32 | ) 33 | } 34 | \arguments{ 35 | \item{model}{a model object fitted with \code{lmer} from package 36 | \pkg{lmerTest}, i.e., an object of class \code{\link{lmerModLmerTest}}.} 37 | 38 | \item{L}{a contrast vector or matrix or a list of these. 39 | The \code{length}/\code{ncol} of each contrasts should equal 40 | \code{length(fixef(model))}.} 41 | 42 | \item{rhs}{right-hand-side of the statistical test, i.e. the hypothesized 43 | value (a numeric scalar).} 44 | 45 | \item{joint}{make an F-test of potentially several contrast vectors? If 46 | \code{FALSE} single DF t-tests are applied to each vector or each row of 47 | contrasts matrices.} 48 | 49 | \item{collect}{collect list of tests in a matrix?} 50 | 51 | \item{confint}{include columns for lower and upper confidence limits? Applies 52 | when \code{joint} is \code{FALSE}.} 53 | 54 | \item{level}{confidence level.} 55 | 56 | \item{check_estimability}{check estimability of contrasts? Only single DF 57 | contrasts are checked for estimability thus requiring \code{joint = FALSE} to 58 | take effect. See details section for necessary adjustments to \code{L} when 59 | estimability is checked with rank deficient design matrices.} 60 | 61 | \item{ddf}{the method for computing the denominator degrees of freedom. 62 | \code{ddf="Kenward-Roger"} uses Kenward-Roger's method.} 63 | 64 | \item{...}{passed to \code{\link{contestMD}}.} 65 | } 66 | \value{ 67 | a \code{data.frame} or a list of \code{data.frame}s. 68 | } 69 | \description{ 70 | Tests of vector or matrix contrasts for \code{\link{lmer}} model fits. 71 | } 72 | \details{ 73 | If the design matrix is rank deficient, \code{lmer} drops columns for the 74 | aliased coefficients from the design matrix and excludes the corresponding 75 | aliased coefficients from \code{fixef(model)}. When estimability is checked 76 | the original rank-deficient design matrix is recontructed and therefore 77 | \code{L} contrast vectors need to include elements for the aliased 78 | coefficients. Similarly when \code{L} is a matrix, its number of columns 79 | needs to match that of the reconstructed rank-deficient design matrix. 80 | } 81 | \examples{ 82 | 83 | data("sleepstudy", package="lme4") 84 | fm <- lmer(Reaction ~ Days + I(Days^2) + (1|Subject) + (0+Days|Subject), 85 | sleepstudy) 86 | # F-test of third coeffcients - I(Days^2): 87 | contest(fm, c(0, 0, 1)) 88 | # Equivalent t-test: 89 | contest(fm, L=c(0, 0, 1), joint=FALSE) 90 | # Test of 'Days + I(Days^2)': 91 | contest(fm, L=diag(3)[2:3, ]) 92 | # Other options: 93 | contest(fm, L=diag(3)[2:3, ], joint=FALSE) 94 | contest(fm, L=diag(3)[2:3, ], joint=FALSE, collect=FALSE) 95 | 96 | # Illustrate a list argument: 97 | L <- list("First"=diag(3)[3, ], "Second"=diag(3)[-1, ]) 98 | contest(fm, L) 99 | contest(fm, L, collect = FALSE) 100 | contest(fm, L, joint=FALSE, confint = FALSE) 101 | contest(fm, L, joint=FALSE, collect = FALSE, level=0.99) 102 | 103 | # Illustrate testing of estimability: 104 | # Consider the 'cake' dataset with a missing cell: 105 | data("cake", package="lme4") 106 | cake$temperature <- factor(cake$temperature, ordered=FALSE) 107 | cake <- droplevels(subset(cake, temperature \%in\% levels(cake$temperature)[1:2] & 108 | !(recipe == "C" & temperature == "185"))) 109 | with(cake, table(recipe, temperature)) 110 | fm <- lmer(angle ~ recipe * temperature + (1|recipe:replicate), cake) 111 | fixef(fm) 112 | # The coefficient for recipeC:temperature185 is dropped: 113 | attr(model.matrix(fm), "col.dropped") 114 | # so any contrast involving this coefficient is not estimable: 115 | Lmat <- diag(6) 116 | contest(fm, Lmat, joint=FALSE, check_estimability = TRUE) 117 | 118 | } 119 | \seealso{ 120 | \code{\link[=contestMD.lmerModLmerTest]{contestMD}} for multi 121 | degree-of-freedom contrast tests, 122 | and \code{\link[=contest1D.lmerModLmerTest]{contest1D}} for tests of 123 | 1-dimensional contrasts. 124 | } 125 | \author{ 126 | Rune Haubo B. Christensen 127 | } 128 | -------------------------------------------------------------------------------- /man/contest1D.lmerModLmerTest.Rd: -------------------------------------------------------------------------------- 1 | % Generated by roxygen2: do not edit by hand 2 | % Please edit documentation in R/contest.R 3 | \name{contest1D.lmerModLmerTest} 4 | \alias{contest1D.lmerModLmerTest} 5 | \alias{contest1D.lmerMod} 6 | \title{Contrast Tests in 1D} 7 | \usage{ 8 | \method{contest1D}{lmerModLmerTest}( 9 | model, 10 | L, 11 | rhs = 0, 12 | ddf = c("Satterthwaite", "Kenward-Roger"), 13 | confint = FALSE, 14 | level = 0.95, 15 | ... 16 | ) 17 | 18 | \method{contest1D}{lmerMod}( 19 | model, 20 | L, 21 | rhs = 0, 22 | ddf = c("Satterthwaite", "Kenward-Roger"), 23 | confint = FALSE, 24 | level = 0.95, 25 | ... 26 | ) 27 | } 28 | \arguments{ 29 | \item{model}{a model object fitted with \code{lmer} from package 30 | \pkg{lmerTest}, i.e., an object of class \code{\link{lmerModLmerTest}}.} 31 | 32 | \item{L}{a numeric (contrast) vector of the same length as 33 | \code{fixef(model)}.} 34 | 35 | \item{rhs}{right-hand-side of the statistical test, i.e. the hypothesized 36 | value (a numeric scalar).} 37 | 38 | \item{ddf}{the method for computing the denominator degrees of freedom. 39 | \code{ddf="Kenward-Roger"} uses Kenward-Roger's method.} 40 | 41 | \item{confint}{include columns for lower and upper confidence limits?} 42 | 43 | \item{level}{confidence level.} 44 | 45 | \item{...}{currently not used.} 46 | } 47 | \value{ 48 | A \code{data.frame} with one row and columns with \code{"Estimate"}, 49 | \code{"Std. Error"}, \code{"t value"}, \code{"df"}, and \code{"Pr(>|t|)"} 50 | (p-value). If \code{confint = TRUE} \code{"lower"} and \code{"upper"} columns 51 | are included before the p-value column. 52 | } 53 | \description{ 54 | Compute the test of a one-dimensional (vector) contrast in a 55 | linear mixed model fitted with lmer from package \pkg{lmerTest}. 56 | The contrast should specify a linear function of the 57 | mean-value parameters, beta. The Satterthwaite or Kenward-Roger method is 58 | used to compute the (denominator) df for the t-test. 59 | } 60 | \details{ 61 | The t-value and associated p-value is for the hypothesis 62 | \eqn{L' \beta = \mathrm{rhs}}{L' \beta = rhs} in which rhs may be non-zero 63 | and \eqn{\beta} is \code{fixef(model)}. 64 | The estimated value (\code{"Estimate"}) is \eqn{L' \beta} with associated 65 | standard error and (optionally) confidence interval. 66 | } 67 | \examples{ 68 | 69 | # Fit model using lmer with data from the lme4-package: 70 | data("sleepstudy", package="lme4") 71 | fm <- lmer(Reaction ~ Days + (1 + Days|Subject), sleepstudy) 72 | 73 | # Tests and CI of model coefficients are obtained with: 74 | contest1D(fm, c(1, 0), confint=TRUE) # Test for Intercept 75 | contest1D(fm, c(0, 1), confint=TRUE) # Test for Days 76 | 77 | # Tests of coefficients are also part of: 78 | summary(fm) 79 | 80 | # Illustrate use of rhs argument: 81 | contest1D(fm, c(0, 1), confint=TRUE, rhs=10) # Test for Days-coef == 10 82 | 83 | 84 | } 85 | \seealso{ 86 | \code{\link[=contest.lmerModLmerTest]{contest}} for a flexible 87 | and general interface to tests of contrasts among fixed-effect parameters. 88 | \code{\link[=contestMD.lmerModLmerTest]{contestMD}} is also available as a 89 | direct interface for tests of multi degree-of-freedom contrast. 90 | } 91 | \author{ 92 | Rune Haubo B. Christensen 93 | } 94 | -------------------------------------------------------------------------------- /man/contestMD.lmerModLmerTest.Rd: -------------------------------------------------------------------------------- 1 | % Generated by roxygen2: do not edit by hand 2 | % Please edit documentation in R/contest.R 3 | \name{contestMD.lmerModLmerTest} 4 | \alias{contestMD.lmerModLmerTest} 5 | \alias{calcSatterth} 6 | \alias{contestMD.lmerMod} 7 | \title{Multiple Degrees-of-Freedom Contrast Tests} 8 | \usage{ 9 | \method{contestMD}{lmerModLmerTest}( 10 | model, 11 | L, 12 | rhs = 0, 13 | ddf = c("Satterthwaite", "Kenward-Roger"), 14 | eps = sqrt(.Machine$double.eps), 15 | ... 16 | ) 17 | 18 | calcSatterth(model, L) 19 | 20 | \method{contestMD}{lmerMod}( 21 | model, 22 | L, 23 | rhs = 0, 24 | ddf = c("Satterthwaite", "Kenward-Roger"), 25 | eps = sqrt(.Machine$double.eps), 26 | ... 27 | ) 28 | } 29 | \arguments{ 30 | \item{model}{a model object fitted with \code{lmer} from package 31 | \pkg{lmerTest}, i.e., an object of class \code{\link{lmerModLmerTest}}.} 32 | 33 | \item{L}{a contrast matrix with nrow >= 1 and ncol == 34 | \code{length(fixef(model))}.} 35 | 36 | \item{rhs}{right-hand-side of the statistical test, i.e. the hypothesized 37 | value. A numeric vector of length \code{nrow(L)} or a numeric scalar.} 38 | 39 | \item{ddf}{the method for computing the denominator degrees of freedom and 40 | F-statistics. \code{ddf="Kenward-Roger"} uses Kenward-Roger's method.} 41 | 42 | \item{eps}{tolerance on eigenvalues to determine if an eigenvalue is 43 | positive. The number of positive eigenvalues determine the rank of 44 | L and the numerator df of the F-test.} 45 | 46 | \item{...}{currently not used.} 47 | } 48 | \value{ 49 | a \code{data.frame} with one row and columns with \code{"Sum Sq"}, 50 | \code{"Mean Sq"}, \code{"F value"}, \code{"NumDF"} (numerator df), 51 | \code{"DenDF"} (denominator df) and \code{"Pr(>F)"} (p-value). 52 | } 53 | \description{ 54 | Compute the multi degrees-of-freedom test in a linear mixed model fitted 55 | by \code{\link{lmer}}. The contrast (L) specifies a linear function of the 56 | mean-value parameters, beta. Satterthwaite's method is used to compute the 57 | denominator df for the F-test. 58 | } 59 | \details{ 60 | The F-value and associated p-value is for the hypothesis 61 | \eqn{L \beta = \mathrm{rhs}}{L \beta = rhs} in which rhs may be non-zero 62 | and \eqn{\beta} is \code{fixef(model)}. 63 | 64 | Note: NumDF = row-rank(L) is determined automatically so row rank-deficient L 65 | are allowed. One-dimensional contrasts are also allowed (L has 1 row). 66 | } 67 | \examples{ 68 | 69 | data("sleepstudy", package="lme4") 70 | fm <- lmer(Reaction ~ Days + I(Days^2) + (1|Subject) + (0+Days|Subject), 71 | sleepstudy) 72 | 73 | # Define 2-df contrast - since L has 2 (linearly independent) rows 74 | # the F-test is on 2 (numerator) df: 75 | L <- rbind(c(0, 1, 0), # Note: ncol(L) == length(fixef(fm)) 76 | c(0, 0, 1)) 77 | 78 | # Make the 2-df F-test of any effect of Days: 79 | contestMD(fm, L) 80 | 81 | # Illustrate rhs argument: 82 | contestMD(fm, L, rhs=c(5, .1)) 83 | 84 | # Make the 1-df F-test of the effect of Days^2: 85 | contestMD(fm, L[2, , drop=FALSE]) 86 | # Same test, but now as a t-test instead: 87 | contest1D(fm, L[2, , drop=TRUE]) 88 | 89 | } 90 | \seealso{ 91 | \code{\link[=contest.lmerModLmerTest]{contest}} for a flexible and 92 | general interface to tests of contrasts among fixed-effect parameters. 93 | \code{\link[=contest1D.lmerModLmerTest]{contest1D}} is a direct interface for 94 | tests of 1-dimensional contrasts. 95 | } 96 | \author{ 97 | Rune Haubo B. Christensen 98 | } 99 | -------------------------------------------------------------------------------- /man/devfun_vp.Rd: -------------------------------------------------------------------------------- 1 | % Generated by roxygen2: do not edit by hand 2 | % Please edit documentation in R/lmer.R 3 | \name{devfun_vp} 4 | \alias{devfun_vp} 5 | \title{Compute Deviance of an LMM as a Function of Variance Parameters} 6 | \usage{ 7 | devfun_vp(varpar, devfun, reml) 8 | } 9 | \arguments{ 10 | \item{varpar}{variance parameters; \code{varpar = c(theta, sigma)}.} 11 | 12 | \item{devfun}{deviance function as a function of theta only.} 13 | 14 | \item{reml}{if \code{TRUE} the REML deviance is computed; 15 | if \code{FALSE}, the ML deviance is computed.} 16 | } 17 | \value{ 18 | the REML or ML deviance. 19 | } 20 | \description{ 21 | This function is used for extracting the asymptotic variance-covariance matrix 22 | of the variance parameters. 23 | } 24 | \author{ 25 | Rune Haubo B. Christensen 26 | } 27 | \keyword{internal} 28 | -------------------------------------------------------------------------------- /man/doolittle.Rd: -------------------------------------------------------------------------------- 1 | % Generated by roxygen2: do not edit by hand 2 | % Please edit documentation in R/contrast_utils.R 3 | \name{doolittle} 4 | \alias{doolittle} 5 | \title{Doolittle Decomposition} 6 | \usage{ 7 | doolittle(x, eps = 1e-06) 8 | } 9 | \arguments{ 10 | \item{x}{a numeric square matrix with at least 2 columns/rows.} 11 | 12 | \item{eps}{numerical tolerance on the whether to normalize with components 13 | in \code{L} with the diagonal elements of \code{U}.} 14 | } 15 | \value{ 16 | a list with two matrices of the same dimension as \code{x}: 17 | \item{L}{lower-left unit-triangular matrix} 18 | \item{U}{upper-right triangular matrix (\emph{not} unit-triangular)} 19 | } 20 | \description{ 21 | Doolittle Decomposition 22 | } 23 | \keyword{internal} 24 | -------------------------------------------------------------------------------- /man/drop1.lmerModLmerTest.Rd: -------------------------------------------------------------------------------- 1 | % Generated by roxygen2: do not edit by hand 2 | % Please edit documentation in R/drop1.R 3 | \name{drop1.lmerModLmerTest} 4 | \alias{drop1.lmerModLmerTest} 5 | \title{Drop Marginal Terms from Model} 6 | \usage{ 7 | \method{drop1}{lmerModLmerTest}( 8 | object, 9 | scope, 10 | ddf = c("Satterthwaite", "Kenward-Roger", "lme4"), 11 | force_get_contrasts = FALSE, 12 | ... 13 | ) 14 | } 15 | \arguments{ 16 | \item{object}{an \code{\link{lmer}} model fit (of class 17 | \code{"lmerModLmerTest"}.)} 18 | 19 | \item{scope}{optional character vector naming terms to be dropped from the 20 | model. Note that only marginal terms can be dropped. To see which terms are 21 | marginal, use \code{drop.scope(terms(object))}.} 22 | 23 | \item{ddf}{the method for computing the denominator degrees of freedom and 24 | F-statistics. \code{ddf="Satterthwaite"} (default) uses Satterthwaite's method; 25 | \code{ddf="Kenward-Roger"} uses Kenward-Roger's method. 26 | \code{ddf = "lme4"} returns the \code{drop1} table for \code{merMod} objects 27 | as defined in package \pkg{lme4}.} 28 | 29 | \item{force_get_contrasts}{enforce computation of contrast matrices by a 30 | method in which the design matrices for full and restricted models are 31 | compared.} 32 | 33 | \item{...}{currently not used.} 34 | } 35 | \value{ 36 | An anova-like table with F-tests of marginal terms. 37 | } 38 | \description{ 39 | Computes the F-test for all marginal terms, i.e. terms that can be dropped 40 | from the model while respecting the hierarchy of terms in the model. 41 | } 42 | \details{ 43 | Simple marginal contrasts are used for all marginal terms unless the design 44 | matrix is rank deficient. In that case (and if \code{force_get_contrasts} is 45 | \code{TRUE}) the contrasts (i.e. restriction matrices on the design matrix 46 | of the full model) are computed by comparison of the design matrices 47 | for full and restricted models. The set of marginal terms considered for 48 | dropping are computed using \code{drop.scope(terms(object))}. 49 | 50 | Since all tests are based on tests of contrasts in the full model, no 51 | models are being (re)fitted. 52 | } 53 | \examples{ 54 | 55 | # Basic usage: 56 | fm <- lmer(angle ~ recipe + temp + (1|recipe:replicate), cake) 57 | drop1(fm) # Using Satterthwaite degrees of freedom 58 | if(requireNamespace("pbkrtest", quietly = TRUE)) 59 | drop1(fm, ddf="Kenward-Roger") # Alternative DenDF and F-test method 60 | drop1(fm, ddf="lme4", test="Chi") # Asymptotic Likelihood ratio tests 61 | 62 | # Consider a rank-deficient design matrix: 63 | fm <- lmer(angle ~ recipe + temp + temperature + (1|recipe:replicate), cake) 64 | # Here temp accounts for the linear effect of temperature, and 65 | # temperature is an (ordered) factor that accounts for the remaining 66 | # variation between temperatures (4 df). 67 | drop1(fm) 68 | # While temperature is in the model, we cannot test the effect of dropping 69 | # temp. After removing temperature we can test the effect of dropping temp: 70 | drop1(lmer(angle ~ recipe + temp + (1|recipe:replicate), cake)) 71 | 72 | # Polynomials: 73 | # Note that linear terms should usually not be dropped before squared terms. 74 | # Therefore 'Days' should not be dropped before 'I(Days^2)' despite it being 75 | # tested here: 76 | fm <- lmer(Reaction ~ Days + I(Days^2) + (Days|Subject), sleepstudy) 77 | drop1(fm) 78 | # Using poly() provides a test of the whole polynomial structure - not a 79 | # separate test for the highest order (squared) term: 80 | fm <- lmer(Reaction ~ poly(Days, 2) + (Days|Subject), sleepstudy) 81 | drop1(fm) 82 | 83 | } 84 | \seealso{ 85 | \code{\link{ranova}} for tests of marginal random terms. 86 | } 87 | \author{ 88 | Rune Haubo B. Christensen 89 | } 90 | -------------------------------------------------------------------------------- /man/ensure_full_rank.Rd: -------------------------------------------------------------------------------- 1 | % Generated by roxygen2: do not edit by hand 2 | % Please edit documentation in R/contrast_utils.R 3 | \name{ensure_full_rank} 4 | \alias{ensure_full_rank} 5 | \title{Ensure a Design Matrix has Full (Column) Rank} 6 | \usage{ 7 | ensure_full_rank(X, tol = 1e-07, silent = FALSE, test.ans = FALSE) 8 | } 9 | \arguments{ 10 | \item{X}{a design matrix as produced by \code{model.matrix}.} 11 | 12 | \item{tol}{\code{qr} tolerance.} 13 | 14 | \item{silent}{throw message if columns are dropped from \code{X}? Default 15 | is \code{FALSE}.} 16 | 17 | \item{test.ans}{Test if the resulting/returned matrix has full rank? Default 18 | is \code{FALSE}.} 19 | } 20 | \value{ 21 | A design matrix in which redundant columns are dropped 22 | } 23 | \description{ 24 | Determine and drop redundant columns using the \code{\link{qr}} 25 | decomposition. 26 | } 27 | \keyword{internal} 28 | -------------------------------------------------------------------------------- /man/get_Fstat_ddf.Rd: -------------------------------------------------------------------------------- 1 | % Generated by roxygen2: do not edit by hand 2 | % Please edit documentation in R/contest.R 3 | \name{get_Fstat_ddf} 4 | \alias{get_Fstat_ddf} 5 | \title{Compute denominator df for F-test} 6 | \usage{ 7 | get_Fstat_ddf(nu, tol = 1e-08) 8 | } 9 | \arguments{ 10 | \item{nu}{vector of denominator df for the t-statistics} 11 | 12 | \item{tol}{tolerance on the consequtive differences between elements of nu to} 13 | } 14 | \value{ 15 | the denominator df; a numerical scalar 16 | } 17 | \description{ 18 | From a vector of denominator df from independent t-statistics (\code{nu}), 19 | the denominator df for the corresponding F-test is computed. 20 | } 21 | \details{ 22 | Note that if any \code{nu <= 2} then \code{2} is returned. Also, if all nu 23 | are within tol of each other the simple average of the nu-vector is returned. 24 | This is to avoid downward bias. 25 | } 26 | \author{ 27 | Rune Haubo B. Christensen 28 | } 29 | \keyword{internal} 30 | -------------------------------------------------------------------------------- /man/get_contrasts_type1.Rd: -------------------------------------------------------------------------------- 1 | % Generated by roxygen2: do not edit by hand 2 | % Please edit documentation in R/anova_contrasts.R 3 | \name{get_contrasts_type1} 4 | \alias{get_contrasts_type1} 5 | \title{Type I ANOVA table contrasts} 6 | \usage{ 7 | get_contrasts_type1(model) 8 | } 9 | \arguments{ 10 | \item{model}{a model object with \code{terms} and \code{model.matrix} methods.} 11 | } 12 | \value{ 13 | List of contrast matrices - one contrast matrix for each model term. 14 | } 15 | \description{ 16 | Type I ANOVA table contrasts 17 | } 18 | \author{ 19 | Rune Haubo B. Christensen 20 | } 21 | \keyword{internal} 22 | -------------------------------------------------------------------------------- /man/get_contrasts_type3.Rd: -------------------------------------------------------------------------------- 1 | % Generated by roxygen2: do not edit by hand 2 | % Please edit documentation in R/anova_contrasts.R 3 | \name{get_contrasts_type3} 4 | \alias{get_contrasts_type3} 5 | \title{Contrasts for Type III Tests} 6 | \usage{ 7 | get_contrasts_type3(model, which = NULL) 8 | } 9 | \arguments{ 10 | \item{model}{model object.} 11 | 12 | \item{which}{optional character vector naming terms for which to compute the 13 | the contrasts.} 14 | } 15 | \value{ 16 | list of contrast matrices. 17 | } 18 | \description{ 19 | Contrasts for Type III Tests 20 | } 21 | \keyword{internal} 22 | -------------------------------------------------------------------------------- /man/get_covbeta.Rd: -------------------------------------------------------------------------------- 1 | % Generated by roxygen2: do not edit by hand 2 | % Please edit documentation in R/lmer.R 3 | \name{get_covbeta} 4 | \alias{get_covbeta} 5 | \title{Compute cov(beta) as a Function of varpar of an LMM} 6 | \usage{ 7 | get_covbeta(varpar, devfun) 8 | } 9 | \arguments{ 10 | \item{varpar}{variance parameters; \code{varpar = c(theta, sigma)}.} 11 | 12 | \item{devfun}{deviance function as a function of theta only.} 13 | } 14 | \value{ 15 | cov(beta) at supplied varpar values. 16 | } 17 | \description{ 18 | At the optimum cov(beta) is available as vcov(lmer-model). This function 19 | computes cov(beta) at non (RE)ML estimates of \code{varpar}. 20 | } 21 | \author{ 22 | Rune Haubo B. Christensen 23 | } 24 | \keyword{internal} 25 | -------------------------------------------------------------------------------- /man/get_model.Rd: -------------------------------------------------------------------------------- 1 | % Generated by roxygen2: do not edit by hand 2 | % Please edit documentation in R/step.R 3 | \name{get_model} 4 | \alias{get_model} 5 | \title{Extract Model from an Object} 6 | \usage{ 7 | get_model(x, ...) 8 | } 9 | \arguments{ 10 | \item{x}{an object.} 11 | 12 | \item{...}{currently not used.} 13 | } 14 | \description{ 15 | Extract Model from an Object 16 | } 17 | \seealso{ 18 | \code{\link{get_model.step_list}} 19 | } 20 | \keyword{internal} 21 | -------------------------------------------------------------------------------- /man/get_model_matrix.Rd: -------------------------------------------------------------------------------- 1 | % Generated by roxygen2: do not edit by hand 2 | % Please edit documentation in R/terms_utils.R 3 | \name{get_model_matrix} 4 | \alias{get_model_matrix} 5 | \title{Extract or remake model matrix from model} 6 | \usage{ 7 | get_model_matrix(model, type = c("extract", "remake"), contrasts = "restore") 8 | } 9 | \arguments{ 10 | \item{model}{an \code{lm} or \code{lmerMod} model object.} 11 | 12 | \item{type}{extract or remake model matrix?} 13 | 14 | \item{contrasts}{contrasts settings. These may be restored to those in the 15 | model or they may be changed. If a length one character vector (e.g. 16 | \code{"contr.SAS"}) this is applied to all factors in the model, but it can 17 | also be a list naming factors for which the contrasts should be set as specified.} 18 | } 19 | \value{ 20 | the model (or 'design') matrix. 21 | } 22 | \description{ 23 | Extract or remake model matrix from model and potentially change the 24 | contrast coding 25 | } 26 | \author{ 27 | Rune Haubo B Christensen 28 | } 29 | \keyword{internal} 30 | -------------------------------------------------------------------------------- /man/get_rdX.Rd: -------------------------------------------------------------------------------- 1 | % Generated by roxygen2: do not edit by hand 2 | % Please edit documentation in R/contrast_utils.R 3 | \name{get_rdX} 4 | \alias{get_rdX} 5 | \title{Compute the 'Full' Rank-Deficient Design Matrix} 6 | \usage{ 7 | get_rdX(model, do.warn = TRUE) 8 | } 9 | \arguments{ 10 | \item{model}{a model object; lmerMod or lmerModLmerTest.} 11 | 12 | \item{do.warn}{throw a message if there is no data for some factor 13 | combinations.} 14 | } 15 | \value{ 16 | the rank-deficien design matrix 17 | } 18 | \description{ 19 | Compute the 'Full' Rank-Deficient Design Matrix 20 | } 21 | \author{ 22 | Rune Haubo B. Christensen 23 | } 24 | \keyword{internal} 25 | -------------------------------------------------------------------------------- /man/ham.Rd: -------------------------------------------------------------------------------- 1 | % Generated by roxygen2: do not edit by hand 2 | % Please edit documentation in R/data_documentation.R 3 | \docType{data} 4 | \name{ham} 5 | \alias{ham} 6 | \title{Conjoint Study of Dry Cured Ham} 7 | \format{ 8 | \describe{ 9 | \item{Consumer}{factor with 81 levels: numbering identifying consumers.} 10 | \item{Product}{factor with four levels.} 11 | \item{Informed.liking}{numeric: hedonic liking for the products.} 12 | \item{Information}{factor with two levels.} 13 | \item{Gender}{factor with two levels.} 14 | \item{Age}{numeric: age of Consumer.} 15 | } 16 | } 17 | \usage{ 18 | data(ham) 19 | } 20 | \description{ 21 | One of the purposes of the study was to investigate the effect of 22 | information given to the consumers measured in hedonic liking for the 23 | hams. Two of the hams were Spanish and two were Norwegian, each origin 24 | representing different salt levels and different aging time. The 25 | information about origin was given in such way that both true and 26 | false information was given. Essentially a 4x2 design with 4 samples 27 | and 2 information levels. A total of 81 Consumers participated in the 28 | study. 29 | } 30 | \examples{ 31 | 32 | # Simple model for the ham data: 33 | fm <- lmer(Informed.liking ~ Product*Information + (1|Consumer) , data=ham) 34 | 35 | # Anova table for the fixed effects: 36 | anova(fm) 37 | 38 | \dontrun{ 39 | # Fit 'big' model: 40 | fm <- lmer(Informed.liking ~ Product*Information*Gender*Age + 41 | + (1|Consumer) + (1|Consumer:Product) + 42 | (1|Consumer:Information), 43 | data=ham) 44 | step_fm <- step(fm) 45 | step_fm # Display elimination results 46 | final_fm <- get_model(step_fm) 47 | } 48 | 49 | } 50 | \references{ 51 | T. Næs, V. Lengard, S. Bølling Johansen, M. Hersleth (2010) 52 | Alternative methods for combining design variables and consumer preference 53 | with information about attitudes and demographics in conjoint analysis, 54 | \emph{Food Quality and Preference}, 10-4, 368-378, ISSN 0950-3293, 55 | \url{https://doi.org/10.1016/j.foodqual.2009.09.004}. 56 | } 57 | \keyword{datasets} 58 | -------------------------------------------------------------------------------- /man/is_estimable.Rd: -------------------------------------------------------------------------------- 1 | % Generated by roxygen2: do not edit by hand 2 | % Please edit documentation in R/estimability.R 3 | \name{is_estimable} 4 | \alias{is_estimable} 5 | \title{Estimability of Contrasts} 6 | \usage{ 7 | is_estimable( 8 | contrast, 9 | nullspace = NULL, 10 | X = NULL, 11 | tol = sqrt(.Machine$double.eps) 12 | ) 13 | } 14 | \arguments{ 15 | \item{contrast}{a numeric matrix where each row is a contrast vector for 16 | which estimability is computed. The matrix should have as many columns as 17 | there are columns in the design matrix (which equals the number of 18 | coefficients). If \code{contrast} is a vector it is coerced to a matrix.} 19 | 20 | \item{nullspace}{the nullspace of the design matrix.} 21 | 22 | \item{X}{design matrix.} 23 | 24 | \item{tol}{tolerance for determining if a contrast is orthogonal to the} 25 | } 26 | \value{ 27 | a logical vector of length \code{nrow(contrast)} determining if each 28 | contrast is estimable 29 | } 30 | \description{ 31 | Computes the estimability of a vector or matrix of contrasts (i.e. linear 32 | functions of the coefficients) from the nullspace of a design matrix or 33 | potentially directly from the design matrix. 34 | } 35 | \examples{ 36 | 37 | # FIXME: We need some examples here 38 | 39 | } 40 | \seealso{ 41 | \code{\link{nullspace}} 42 | } 43 | \author{ 44 | Rune Haubo B. Christensen 45 | } 46 | \keyword{internal} 47 | -------------------------------------------------------------------------------- /man/legacy.Rd: -------------------------------------------------------------------------------- 1 | % Generated by roxygen2: do not edit by hand 2 | % Please edit documentation in R/legacy.R 3 | \name{anova.merModLmerTest} 4 | \alias{anova.merModLmerTest} 5 | \alias{legacy} 6 | \alias{summary.merModLmerTest} 7 | \alias{ls_means.merModLmerTest} 8 | \alias{lsmeansLT.merModLmerTest} 9 | \alias{difflsmeans.merModLmerTest} 10 | \alias{drop1.merModLmerTest} 11 | \alias{step.merModLmerTest} 12 | \title{Methods for Legacy lmerTest Objects} 13 | \usage{ 14 | \method{anova}{merModLmerTest}( 15 | object, 16 | ..., 17 | type = c("III", "II", "I", "3", "2", "1"), 18 | ddf = c("Satterthwaite", "Kenward-Roger", "lme4") 19 | ) 20 | 21 | \method{summary}{merModLmerTest}(object, ..., ddf = c("Satterthwaite", "Kenward-Roger", "lme4")) 22 | 23 | \method{ls_means}{merModLmerTest}( 24 | model, 25 | which = NULL, 26 | level = 0.95, 27 | ddf = c("Satterthwaite", "Kenward-Roger"), 28 | pairwise = FALSE, 29 | ... 30 | ) 31 | 32 | \method{lsmeansLT}{merModLmerTest}( 33 | model, 34 | which = NULL, 35 | level = 0.95, 36 | ddf = c("Satterthwaite", "Kenward-Roger"), 37 | pairwise = FALSE, 38 | ... 39 | ) 40 | 41 | \method{difflsmeans}{merModLmerTest}( 42 | model, 43 | which = NULL, 44 | level = 0.95, 45 | ddf = c("Satterthwaite", "Kenward-Roger"), 46 | ... 47 | ) 48 | 49 | \method{drop1}{merModLmerTest}( 50 | object, 51 | scope, 52 | ddf = c("Satterthwaite", "Kenward-Roger", "lme4"), 53 | force_get_contrasts = FALSE, 54 | ... 55 | ) 56 | 57 | \method{step}{merModLmerTest}( 58 | object, 59 | ddf = c("Satterthwaite", "Kenward-Roger"), 60 | alpha.random = 0.1, 61 | alpha.fixed = 0.05, 62 | reduce.fixed = TRUE, 63 | reduce.random = TRUE, 64 | keep, 65 | ... 66 | ) 67 | } 68 | \arguments{ 69 | \item{object}{an \code{lmerModLmerTest} object; the result of \code{lmer()} 70 | after loading the \pkg{lmerTest}-package.} 71 | 72 | \item{...}{for the anova method optionally additional models; for other 73 | methods see the corresponding \code{lmerModLmerTest} methods for details.} 74 | 75 | \item{type}{the type of ANOVA table requested (using SAS terminology) 76 | with Type I being the familiar sequential ANOVA table.} 77 | 78 | \item{ddf}{the method for computing the denominator degrees of freedom and 79 | F-statistics. \code{ddf="Satterthwaite"} (default) uses Satterthwaite's method; 80 | \code{ddf="Kenward-Roger"} uses Kenward-Roger's method, 81 | \code{ddf = "lme4"} returns the lme4-anova table, i.e., using the anova 82 | method for \code{lmerMod} objects as defined in the \pkg{lme4}-package and 83 | ignores the \code{type} argument. Partial matching is allowed.} 84 | 85 | \item{model}{a model object fitted with \code{\link{lmer}} (of class 86 | \code{"lmerModLmerTest"}).} 87 | 88 | \item{which}{optional character vector naming factors for which LS-means should 89 | be computed. If \code{NULL} (default) LS-means for all factors are computed.} 90 | 91 | \item{level}{confidence level.} 92 | 93 | \item{pairwise}{compute pairwise differences of LS-means instead?} 94 | 95 | \item{scope}{optional character vector naming terms to be dropped from the 96 | model. Note that only marginal terms can be dropped. To see which terms are 97 | marginal, use \code{drop.scope(terms(object))}.} 98 | 99 | \item{force_get_contrasts}{enforce computation of contrast matrices by a 100 | method in which the design matrices for full and restricted models are 101 | compared.} 102 | 103 | \item{alpha.random}{alpha for random effects elimination} 104 | 105 | \item{alpha.fixed}{alpha for fixed effects elimination} 106 | 107 | \item{reduce.fixed}{reduce fixed effect structure? \code{TRUE} by default.} 108 | 109 | \item{reduce.random}{reduce random effect structure? \code{TRUE} by default.} 110 | 111 | \item{keep}{an optional character vector of fixed effect terms which should 112 | not be considered for eliminated. Valid terms are given by 113 | \code{attr(terms(object), "term.labels")}. Terms that are marginal to terms 114 | in keep will also not be considered for eliminations.} 115 | } 116 | \description{ 117 | Methods are defined for legacy lmerTest objects of class 118 | \code{merModLmerTest} generated with \pkg{lmerTest} version \code{< 3.0-0}. 119 | These methods are defined by interfacing code for \code{lmerModLmerTest} 120 | methods and therefore behaves like these methods do (which may differ from 121 | the behavior of \pkg{lmerTest} version \code{< 3.0-0}.) 122 | } 123 | \examples{ 124 | # Load model fits fm1 and fm2 generated with lmerTest version 2.3-37: 125 | load(system.file("testdata","legacy_fits.RData", package="lmerTest")) 126 | 127 | # Apply some methods defined by lmerTest: 128 | anova(fm1) 129 | summary(fm1) 130 | contest(fm1, c(0, 1)) 131 | contest(fm1, c(0, 1), joint=FALSE) 132 | drop1(fm1) 133 | ranova(fm1) 134 | 135 | # lme4-methods also work: 136 | fixef(fm1) 137 | 138 | # Ditto for second model fit: 139 | anova(fm2) 140 | summary(fm2) 141 | ls_means(fm2) 142 | difflsmeans(fm2) 143 | } 144 | \author{ 145 | Rune Haubo B. Christensen 146 | } 147 | \keyword{internal} 148 | -------------------------------------------------------------------------------- /man/lmer.Rd: -------------------------------------------------------------------------------- 1 | % Generated by roxygen2: do not edit by hand 2 | % Please edit documentation in R/lmer.R 3 | \name{lmer} 4 | \alias{lmer} 5 | \title{Fit Linear Mixed-Effects Models} 6 | \usage{ 7 | lmer( 8 | formula, 9 | data = NULL, 10 | REML = TRUE, 11 | control = lmerControl(), 12 | start = NULL, 13 | verbose = 0L, 14 | subset, 15 | weights, 16 | na.action, 17 | offset, 18 | contrasts = NULL, 19 | devFunOnly = FALSE 20 | ) 21 | } 22 | \arguments{ 23 | \item{formula}{a two-sided linear formula object describing both the 24 | fixed-effects and random-effects part of the model, with the 25 | response on the left of a \code{~} operator and the terms, separated 26 | by \code{+} operators, on the right. Random-effects terms are 27 | distinguished by vertical bars (\code{|}) separating expressions 28 | for design matrices from grouping factors. Two vertical bars 29 | (\code{||}) can be used to specify multiple uncorrelated random 30 | effects for the same grouping variable. %---------- 31 | (Because of the way it is implemented, the \code{||}-syntax \emph{works 32 | only for design matrices containing numeric (continuous) predictors}; 33 | to fit models with independent categorical effects, see \code{\link[lme4]{dummy}} 34 | or the \code{lmer_alt} function from the \href{https://CRAN.R-project.org/package=afex}{\pkg{afex}} package.) 35 | } 36 | 37 | \item{data}{an optional data frame containing the variables named in 38 | \code{formula}. By default the variables are taken from the 39 | environment from which \code{lmer} is called. While \code{data} is 40 | optional, the package authors \emph{strongly} recommend its use, 41 | especially when later applying methods such as \code{update} and 42 | \code{drop1} to the fitted model (\emph{such methods are not 43 | guaranteed to work properly if \code{data} is omitted}). If 44 | \code{data} is omitted, variables will be taken from the environment 45 | of \code{formula} (if specified as a formula) or from the parent 46 | frame (if specified as a character vector).} 47 | 48 | \item{REML}{logical scalar - Should the estimates be chosen to 49 | optimize the REML criterion (as opposed to the log-likelihood)?} 50 | 51 | \item{control}{a list (of correct class, resulting from 52 | \code{\link[lme4]{lmerControl}()} or \code{\link[lme4]{glmerControl}()} 53 | respectively) containing control parameters, including the nonlinear 54 | optimizer to be used and parameters to be passed through to the 55 | nonlinear optimizer, see the \code{*lmerControl} documentation for 56 | details.} 57 | 58 | \item{start}{a named \code{\link{list}} of starting values for the 59 | parameters in the model. For \code{lmer} this can be a numeric 60 | vector or a list with one component named \code{"theta"}.} 61 | 62 | \item{verbose}{integer scalar. If \code{> 0} verbose output is 63 | generated during the optimization of the parameter estimates. If 64 | \code{> 1} verbose output is generated during the individual 65 | penalized iteratively reweighted least squares (PIRLS) steps.} 66 | 67 | \item{subset}{an optional expression indicating the subset of the rows 68 | of \code{data} that should be used in the fit. This can be a logical 69 | vector, or a numeric vector indicating which observation numbers are 70 | to be included, or a character vector of the row names to be 71 | included. All observations are included by default.} 72 | 73 | \item{weights}{an optional vector of \sQuote{prior weights} to be used 74 | in the fitting process. Should be \code{NULL} or a numeric vector. 75 | Prior \code{weights} are \emph{not} normalized or standardized in 76 | any way. In particular, the diagonal of the residual covariance 77 | matrix is the squared residual standard deviation parameter 78 | \code{\link[lme4]{sigma}} times the vector of inverse \code{weights}. 79 | Therefore, if the \code{weights} have relatively large magnitudes, 80 | then in order to compensate, the \code{\link[lme4]{sigma}} parameter will 81 | also need to have a relatively large magnitude.} 82 | 83 | \item{na.action}{a function that indicates what should happen when the 84 | data contain \code{NA}s. The default action (\code{na.omit}, 85 | inherited from the 'factory fresh' value of 86 | \code{getOption("na.action")}) strips any observations with any 87 | missing values in any variables.} 88 | 89 | \item{offset}{this can be used to specify an \emph{a priori} known 90 | component to be included in the linear predictor during 91 | fitting. This should be \code{NULL} or a numeric vector of length 92 | equal to the number of cases. One or more \code{\link{offset}} 93 | terms can be included in the formula instead or as well, and if more 94 | than one is specified their sum is used. See 95 | \code{\link{model.offset}}.} 96 | 97 | \item{contrasts}{an optional list. See the \code{contrasts.arg} of 98 | \code{model.matrix.default}.} 99 | 100 | \item{devFunOnly}{logical - return only the deviance evaluation 101 | function. Note that because the deviance function operates on 102 | variables stored in its environment, it may not return 103 | \emph{exactly} the same values on subsequent calls (but the results 104 | should always be within machine tolerance).} 105 | } 106 | \value{ 107 | an S4 object of class \code{"lmerModLmerTest"} 108 | } 109 | \description{ 110 | This function overloads \code{\link[lme4]{lmer}} from the \pkg{lme4}-package 111 | (\code{lme4::lmer}) and adds a couple of slots needed for the computation of 112 | Satterthwaite denominator degrees of freedom. All arguments are the same as 113 | for \code{lme4::lmer} and all the usual \code{lmer}-methods work. 114 | } 115 | \details{ 116 | For details about \code{lmer} see \code{\link[lme4]{lmer}} 117 | (\code{help(lme4::lmer)}). The description of all arguments is taken 118 | unedited from the \pkg{lme4}-package. 119 | 120 | In cases when a valid \code{lmer}-object 121 | (\code{lmerMod}) is produced, but when the computations needed for 122 | Satterthwaite df fails, the \code{lmerMod} object is returned - not an 123 | \code{lmerModLmerTest} object. 124 | } 125 | \examples{ 126 | 127 | data("sleepstudy", package="lme4") 128 | m <- lmer(Reaction ~ Days + (Days | Subject), sleepstudy) 129 | class(m) # lmerModLmerTest 130 | 131 | } 132 | \seealso{ 133 | \code{\link[lme4]{lmer}} and \code{\link{lmerModLmerTest}} 134 | } 135 | \author{ 136 | Rune Haubo B. Christensen and Alexandra Kuznetsova for the overload 137 | in \pkg{lmerTest} -- \pkg{lme4}-authors for the underlying implementation 138 | in \pkg{lme4}. 139 | } 140 | -------------------------------------------------------------------------------- /man/lmerModLmerTest-class.Rd: -------------------------------------------------------------------------------- 1 | % Generated by roxygen2: do not edit by hand 2 | % Please edit documentation in R/lmer.R 3 | \docType{class} 4 | \name{lmerModLmerTest-class} 5 | \alias{lmerModLmerTest-class} 6 | \alias{lmerModLmerTest} 7 | \title{Represent Linear Mixed-Effects Models} 8 | \value{ 9 | An object of class \code{lmerModLmerTest} with slots as in 10 | \code{lmerMod} objects (see \code{\link[lme4]{merMod}}) and a few 11 | additional slots as described in the slots section. 12 | } 13 | \description{ 14 | The \code{lmerModLmerTest} class extends \code{lmerMod} (which extends 15 | \code{merMod}) from the \pkg{lme4}-package. 16 | } 17 | \section{Slots}{ 18 | 19 | \describe{ 20 | \item{\code{vcov_varpar}}{a numeric matrix holding the asymptotic variance-covariance 21 | matrix of the variance parameters (including sigma).} 22 | 23 | \item{\code{Jac_list}}{a list of gradient matrices (Jacobians) for the gradient of 24 | the variance-covariance of beta with respect to the variance parameters, 25 | where beta are the mean-value parameters available in \code{fixef(object)}.} 26 | 27 | \item{\code{vcov_beta}}{a numeric matrix holding the asymptotic variance-covariance 28 | matrix of the fixed-effect regression parameters (beta).} 29 | 30 | \item{\code{sigma}}{the residual standard deviation.} 31 | }} 32 | 33 | \seealso{ 34 | \code{\link[lme4]{lmer}} and \code{\link[lme4]{merMod}} 35 | } 36 | \author{ 37 | Rune Haubo B. Christensen 38 | } 39 | -------------------------------------------------------------------------------- /man/lmerTest-package.Rd: -------------------------------------------------------------------------------- 1 | % Generated by roxygen2: do not edit by hand 2 | % Please edit documentation in R/lmerTest.R 3 | \docType{package} 4 | \name{lmerTest-package} 5 | \alias{lmerTest-package} 6 | \alias{lmerTest} 7 | \title{lmerTest: Tests in Linear Mixed Effects Models} 8 | \description{ 9 | The \pkg{lmerTest} package provides p-values in type I, II or III 10 | \code{anova} and \code{summary} 11 | tables for linear mixed models (\code{\link{lmer}} model fits cf. \pkg{lme4}) 12 | via Satterthwaite's degrees of freedom method; a Kenward-Roger method is also 13 | available via the \pkg{pbkrtest} package. 14 | Model selection and assessment methods include \code{\link{step}}, 15 | \code{\link{drop1}}, anova-like tables for random effects (\code{\link{ranova}}), 16 | least-square means (LS-means; \code{\link{ls_means}}) 17 | and tests of linear contrasts of fixed effects (\code{\link{contest}}). 18 | } 19 | \section{Key Functions and Methods}{ 20 | 21 | 22 | \describe{ 23 | \item{lmer}{overloads \code{lme4::lmer} and produced an object of class 24 | \code{lmerModLmerTest} which inherits from \code{lmerMod}. In addition to 25 | computing the model (using \code{lme4::lmer}), \code{lmerTest::lmer} 26 | computes a couple of components needed for the evaluation of Satterthwaite's 27 | denominator degrees of freedom.} 28 | \item{anova}{anova method for \code{\link{lmer}} model fits produces 29 | type I, II, and III anova tables for fixed-effect terms with 30 | Satterthwaite and Kenward-Roger methods for denominator degrees of freedom 31 | for F-tests.} 32 | \item{summary}{summary method for \code{\link{lmer}} model fits adds 33 | denominator degrees of freedom and p-values to the coefficient table.} 34 | \item{ranova}{anova-like table of random effects via likelihood ratio tests 35 | with methods for both \code{lmerMod} and \code{lmerModLmerTest} objects. 36 | \code{ranova} can either test reduction of random-effect terms to simpler 37 | structures or it can test removal of entire random-effect terms.} 38 | \item{drop1}{F-tests of fixed-effect terms using Satterthwaite or 39 | Kenward-Roger methods for denominator degrees of freedom. These 'single term 40 | deletion' tables are useful for model selection and tests of marginal terms. 41 | Compared to the likelihood ratio tests of \code{lme4::drop1} the F-tests and 42 | p-values of \code{lmerTest::drop1} are more accurate and considerably faster 43 | since no additional model fitting is required.} 44 | \item{contest}{tests of contrasts, i.e. tests of linear functions of the 45 | fixed-effect coefficients. A user-friendly interface for tests of contrasts 46 | with outputs either as a summary-like table of t-tests or an anova-like table 47 | of F-tests (or a list of either). Contrasts can optionally be tested for 48 | estimability. Contrasts are allowed to be rank-deficient as the rank is 49 | automatically detected and appropriate adjustments made. Methods for 50 | \code{lmerModLmerTest} as well as \code{lmerMod} objects -- the latter avoids 51 | the Satterthwaite specific computations when the Kenward-Roger method is used.} 52 | \item{show_test}{a function which operates on anova tables and LS-means tables 53 | makes it possible to see exactly which 54 | functions of the coefficients are being tested. This is helpful when 55 | differences between type I, II and III anova tables are being considered and 56 | discussed.} 57 | \item{ls_means}{computes the so-called least-squares means (classical Yates 58 | contrasts) as well as pairwise differences of these.} 59 | \item{step}{performs automatic backward model selection of fixed and random 60 | parts of the linear mixed model.} 61 | \item{as_lmerModLmerTest}{an explicit coerce function from class 62 | \code{lmerMod} to \code{lmerModLmerTest}.} 63 | } 64 | } 65 | 66 | \section{Details}{ 67 | 68 | The computational approach is to let \code{lmerTest::lmer} compute the 69 | Hessian and derivatives needed for evaluation of degrees of freedom and 70 | t- and F-tests and to store these in the model object. The 71 | Hessian and derivatives are therefore computed only once per model fit 72 | and reused with each call to \code{anova}, \code{summary}, etc. Evaluation of 73 | t and F-tests does not involve model re-fitting. 74 | 75 | \code{lmerTest::lmer} roughly amounts to calling \code{lme4::lmer} followed by 76 | \code{lmerTest::as_lmerModLmerTest}, so for computationally intensive model 77 | fits it can make sense to use \code{lme4::lmer} rather than \code{lmerTest::lmer} 78 | if computational time is an issue and summary tables and anova tables will 79 | not be needed. 80 | } 81 | 82 | \examples{ 83 | 84 | ## load lmerTest package 85 | library(lmerTest) 86 | 87 | ## Fit linear mixed model to the ham data: 88 | fm <- lmer(Informed.liking ~ Gender + Information * Product + (1 | Consumer) + 89 | (1 | Consumer:Product), data=ham) 90 | 91 | ## Summary including coefficient table with p-values for t-statistics using 92 | ## Satterthwaite's method for denominator degrees of freedom: 93 | summary(fm) 94 | 95 | ## Type III anova table with p-values for F-tests based on Satterthwaite's 96 | ## method: 97 | (aov <- anova(fm)) 98 | 99 | ## Inspect the contrast matrix for the Type III test of Product: 100 | show_tests(aov, fractions = TRUE)$Product 101 | 102 | ## Choose type II anova table with Kenward-Roger method for the F-test: 103 | \dontrun{ 104 | if(requireNamespace("pbkrtest", quietly = TRUE)) 105 | anova(fm, type=2, ddf="Kenward-Roger") 106 | } 107 | 108 | ## Anova-like table of random-effect terms using likelihood ratio tests: 109 | ranova(fm) 110 | 111 | ## F-tests of 'single term deletions' for all marginal terms: 112 | drop1(fm) 113 | 114 | ## Least-Square means and pairwise differences: 115 | (lsm <- ls_means(fm)) 116 | ls_means(fm, which = "Product", pairwise = TRUE) 117 | 118 | ## ls_means also have plot and as.data.frame methods: 119 | \dontrun{ 120 | plot(lsm, which=c("Product", "Information")) 121 | as.data.frame(lsm) 122 | ## Inspect the LS-means contrasts: 123 | show_tests(lsm, fractions=TRUE)$Product 124 | } 125 | 126 | ## Contrast test (contest) using a custom contrast: 127 | ## Here we make the 2-df joint test of the main effects of Gender and Information 128 | (L <- diag(length(fixef(fm)))[2:3, ]) 129 | contest(fm, L = L) 130 | 131 | ## backward elimination of non-significant effects: 132 | step_result <- step(fm) 133 | 134 | ## Elimination tables for random- and fixed-effect terms: 135 | step_result 136 | 137 | # Extract the model that step found: 138 | final_model <- get_model(step_result) 139 | 140 | } 141 | \references{ 142 | Alexandra Kuznetsova, Per B. Brockhoff and Rune H. B. Christensen (2017) 143 | lmerTest Package: Tests in Linear Mixed Effects Models. 144 | \emph{Journal of Statistical Software}, 82(13), 1--26. doi:10.18637/jss.v082.i13 145 | } 146 | \author{ 147 | Alexandra Kuznetsova, Per Bruun Brockhoff, Rune Haubo Bojesen Christensen 148 | } 149 | -------------------------------------------------------------------------------- /man/ls_means.Rd: -------------------------------------------------------------------------------- 1 | % Generated by roxygen2: do not edit by hand 2 | % Please edit documentation in R/ls_means.R 3 | \name{ls_means} 4 | \alias{ls_means} 5 | \alias{difflsmeans} 6 | \alias{lsmeansLT} 7 | \title{LS-means Generic Function} 8 | \usage{ 9 | ls_means(model, ...) 10 | 11 | difflsmeans(model, ...) 12 | 13 | lsmeansLT(model, ...) 14 | } 15 | \arguments{ 16 | \item{model}{a model object.} 17 | 18 | \item{...}{parsed on to methods.} 19 | } 20 | \description{ 21 | LS-means Generic Function 22 | } 23 | \seealso{ 24 | \code{\link{ls_means.lmerModLmerTest}} 25 | 26 | \code{\link{difflsmeans.lmerModLmerTest}} 27 | 28 | \code{\link{lsmeansLT.lmerModLmerTest}} 29 | } 30 | \author{ 31 | Rune Haubo B. Christensen 32 | } 33 | \keyword{internal} 34 | -------------------------------------------------------------------------------- /man/ls_means.lmerModLmerTest.Rd: -------------------------------------------------------------------------------- 1 | % Generated by roxygen2: do not edit by hand 2 | % Please edit documentation in R/ls_means.R 3 | \name{ls_means.lmerModLmerTest} 4 | \alias{ls_means.lmerModLmerTest} 5 | \alias{lsmeansLT.lmerModLmerTest} 6 | \alias{difflsmeans.lmerModLmerTest} 7 | \title{LS-means for lmerTest Model Fits} 8 | \usage{ 9 | \method{ls_means}{lmerModLmerTest}( 10 | model, 11 | which = NULL, 12 | level = 0.95, 13 | ddf = c("Satterthwaite", "Kenward-Roger"), 14 | pairwise = FALSE, 15 | ... 16 | ) 17 | 18 | \method{lsmeansLT}{lmerModLmerTest}( 19 | model, 20 | which = NULL, 21 | level = 0.95, 22 | ddf = c("Satterthwaite", "Kenward-Roger"), 23 | pairwise = FALSE, 24 | ... 25 | ) 26 | 27 | \method{difflsmeans}{lmerModLmerTest}( 28 | model, 29 | which = NULL, 30 | level = 0.95, 31 | ddf = c("Satterthwaite", "Kenward-Roger"), 32 | ... 33 | ) 34 | } 35 | \arguments{ 36 | \item{model}{a model object fitted with \code{\link{lmer}} (of class 37 | \code{"lmerModLmerTest"}).} 38 | 39 | \item{which}{optional character vector naming factors for which LS-means should 40 | be computed. If \code{NULL} (default) LS-means for all factors are computed.} 41 | 42 | \item{level}{confidence level.} 43 | 44 | \item{ddf}{method for computation of denominator degrees of freedom.} 45 | 46 | \item{pairwise}{compute pairwise differences of LS-means instead?} 47 | 48 | \item{...}{currently not used.} 49 | } 50 | \value{ 51 | An LS-means table in the form of a \code{data.frame}. Formally an object 52 | of class \code{c("ls_means", "data.frame")} with a number of attributes set. 53 | } 54 | \description{ 55 | Computes LS-means or pairwise differences of LS-mean for all factors in a 56 | linear mixed model. \code{lsmeansLT} is provided as an alias for 57 | \code{ls_means} for backward compatibility. 58 | } 59 | \details{ 60 | Confidence intervals and p-values are based on the t-distribution using 61 | degrees of freedom based on Satterthwaites or Kenward-Roger methods. 62 | 63 | LS-means is SAS terminology for predicted/estimated marginal means, i.e. means 64 | for levels of factors which are averaged over the levels of other factors in 65 | the model. A flat (i.e. unweighted) average is taken which gives equal weight 66 | to all levels of each of the other factors. Numeric/continuous variables are 67 | set at their mean values. See \pkg{emmeans} package 68 | for more options and greater flexibility. 69 | 70 | LS-means contrasts are checked for estimability and unestimable contrasts appear 71 | as \code{NA}s in the resulting table. 72 | 73 | LS-means objects (of class \code{"ls_means"} have a print method). 74 | } 75 | \examples{ 76 | 77 | # Get data and fit model: 78 | data("cake", package="lme4") 79 | model <- lmer(angle ~ recipe * temp + (1|recipe:replicate), cake) 80 | 81 | # Compute LS-means: 82 | ls_means(model) 83 | 84 | # Get LS-means contrasts: 85 | show_tests(ls_means(model)) 86 | 87 | # Compute pairwise differences of LS-means for each factor: 88 | ls_means(model, pairwise=TRUE) 89 | difflsmeans(model) # Equivalent. 90 | 91 | } 92 | \seealso{ 93 | \code{\link[=show_tests.ls_means]{show_tests}} for display of the 94 | underlying LS-means contrasts. 95 | } 96 | \author{ 97 | Rune Haubo B. Christensen and Alexandra Kuznetsova 98 | } 99 | -------------------------------------------------------------------------------- /man/merModLmerTest-class.Rd: -------------------------------------------------------------------------------- 1 | % Generated by roxygen2: do not edit by hand 2 | % Please edit documentation in R/legacy.R 3 | \docType{class} 4 | \name{merModLmerTest-class} 5 | \alias{merModLmerTest-class} 6 | \alias{merModLmerTest} 7 | \title{Legacy lmerTest representation of Linear Mixed-Effects Models} 8 | \description{ 9 | The \code{merModLmerTest} class extends \code{lmerMod} (which extends 10 | \code{merMod}) from the \pkg{lme4}-package. 11 | } 12 | \author{ 13 | Rune Haubo B. Christensen 14 | } 15 | \keyword{internal} 16 | -------------------------------------------------------------------------------- /man/nullspace.Rd: -------------------------------------------------------------------------------- 1 | % Generated by roxygen2: do not edit by hand 2 | % Please edit documentation in R/estimability.R 3 | \name{nullspace} 4 | \alias{nullspace} 5 | \title{Nullspace} 6 | \usage{ 7 | nullspace(A, type = c("right", "left"), tol = sqrt(.Machine$double.eps)) 8 | } 9 | \arguments{ 10 | \item{A}{a numeric matrix.} 11 | 12 | \item{type}{\code{"right"} (default) gives is the standard nullspace, 13 | \code{"left"} gives left nullspace of \code{A}.} 14 | 15 | \item{tol}{tolerance multiple of the first singular value to determine if 16 | subsequent singular values are (sufficiently) positive to be determined 17 | greater than zero.} 18 | } 19 | \value{ 20 | a matrix with as many rows as there are columns in \code{A}. The 21 | number of columns (which may be zero) determine the dimensionality of the 22 | nullspace of \code{A}. 23 | } 24 | \description{ 25 | Compute the (right or left) nullspace of matrix using a (semi-complete) 26 | Singular Value Decomposition. 27 | } 28 | \details{ 29 | This implementation is fastest on matrices with more rows 30 | than columns such as a typical design matrix for a linear model. 31 | } 32 | \examples{ 33 | 34 | # FIXME: We need some examples here 35 | 36 | } 37 | \author{ 38 | Rune Haubo B. Christensen 39 | } 40 | \keyword{internal} 41 | -------------------------------------------------------------------------------- /man/plot.ls_means.Rd: -------------------------------------------------------------------------------- 1 | % Generated by roxygen2: do not edit by hand 2 | % Please edit documentation in R/ls_means.R 3 | \name{plot.ls_means} 4 | \alias{plot.ls_means} 5 | \title{Bar Plots of LS-Means} 6 | \usage{ 7 | \method{plot}{ls_means}(x, y = NULL, which = NULL, mult = TRUE, ...) 8 | } 9 | \arguments{ 10 | \item{x}{an \code{\link{ls_means}} object.} 11 | 12 | \item{y}{not used and ignored with a warning.} 13 | 14 | \item{which}{optional character vector naming factors for which LS-means should 15 | be plotted. If \code{NULL} (default) plots for all LS-means are generated.} 16 | 17 | \item{mult}{if \code{TRUE} and there is more than one term for which to plot 18 | LS-means the plots are organized in panels with \code{facet_wrap}.} 19 | 20 | \item{...}{currently not used.} 21 | } 22 | \value{ 23 | generates the desired plots and invisibly returns the plot objects. 24 | } 25 | \description{ 26 | Bar plots of LS-means using the \pkg{ggplot2} package. 27 | } 28 | \examples{ 29 | 30 | # Fit example model with 2 factors: 31 | data("cake", package="lme4") 32 | cake$Temp <- factor(cake$temperature, ordered = FALSE) 33 | model <- lmer(angle ~ recipe * Temp + (1|recipe:replicate), cake) 34 | 35 | # Extract LS-means: 36 | (lsm <- ls_means(model)) 37 | 38 | # Multi-frame plot of the LS-means 39 | plot(lsm) 40 | 41 | # Compute list of 'single frame' plots: 42 | res <- plot(lsm, mult=FALSE) 43 | 44 | # Display each plot separately: 45 | plot(res[[1]]) 46 | plot(res[[2]]) 47 | 48 | # Example with pairwise differences of LS-means: 49 | (lsm <- ls_means(model, pairwise = TRUE)) 50 | plot(lsm, which="Temp") 51 | 52 | } 53 | \seealso{ 54 | \code{\link{ls_means.lmerModLmerTest}} 55 | } 56 | \author{ 57 | Rune Haubo B. Christensen 58 | } 59 | \keyword{internal} 60 | -------------------------------------------------------------------------------- /man/plot.step_list.Rd: -------------------------------------------------------------------------------- 1 | % Generated by roxygen2: do not edit by hand 2 | % Please edit documentation in R/step.R 3 | \name{plot.step_list} 4 | \alias{plot.step_list} 5 | \title{Plot LS-means for Backward Reduced Model} 6 | \usage{ 7 | \method{plot}{step_list}( 8 | x, 9 | y = NULL, 10 | which = NULL, 11 | pairwise = FALSE, 12 | mult = TRUE, 13 | level = 0.95, 14 | ddf = c("Satterthwaite", "Kenward-Roger"), 15 | ... 16 | ) 17 | } 18 | \arguments{ 19 | \item{x}{a \code{step_list} object; the result of running 20 | \code{\link[=step.lmerModLmerTest]{step}}.} 21 | 22 | \item{y}{not used and ignored with a warning.} 23 | 24 | \item{which}{optional character vector naming factors for which LS-means should 25 | be plotted. If \code{NULL} (default) plots for all LS-means are generated.} 26 | 27 | \item{pairwise}{pairwise differences of LS-means?} 28 | 29 | \item{mult}{if \code{TRUE} and there is more than one term for which to plot 30 | LS-means the plots are organized in panels with \code{facet_wrap}.} 31 | 32 | \item{level}{confidence level.} 33 | 34 | \item{ddf}{denominator degree of freedom method.} 35 | 36 | \item{...}{currently not used.} 37 | } 38 | \description{ 39 | Computes the LS-means for the final backward reduced model and passes these 40 | to \code{\link{plot.ls_means}}. 41 | } 42 | \details{ 43 | Error bars are confidence intervals - the default is 95% CI but the confidence 44 | level can be changed. 45 | } 46 | \examples{ 47 | 48 | \dontrun{ 49 | # Fit example model: 50 | tv <- lmer(Sharpnessofmovement ~ TVset * Picture + 51 | (1 | Assessor:TVset) + (1 | Assessor:Picture) + 52 | (1 | Assessor:Picture:TVset) + (1 | Repeat) + (1 | Repeat:Picture) + 53 | (1 | Repeat:TVset) + (1 | Repeat:TVset:Picture) + (1 | Assessor), 54 | data = TVbo) 55 | 56 | # Backward reduce the model: 57 | (st <- step(tv)) # takes ~10 sec to run 58 | 59 | # Pairwise comparisons of LS-means for Picture and TVset: 60 | plot(st, which=c("Picture", "TVset"), pairwise = TRUE) 61 | } 62 | 63 | } 64 | \seealso{ 65 | \code{\link[=ls_means.lmerModLmerTest]{ls_means}} and 66 | \code{\link{plot.ls_means}} 67 | } 68 | \author{ 69 | Rune Haubo B. Christensen and Alexandra Kuznetsova 70 | } 71 | \keyword{internal} 72 | -------------------------------------------------------------------------------- /man/qform.Rd: -------------------------------------------------------------------------------- 1 | % Generated by roxygen2: do not edit by hand 2 | % Please edit documentation in R/utils.R 3 | \name{qform} 4 | \alias{qform} 5 | \title{Compute Quadratic Form} 6 | \usage{ 7 | qform(x, A) 8 | } 9 | \arguments{ 10 | \item{x}{a numeric vector} 11 | 12 | \item{A}{a symmetric numeric matrix} 13 | } 14 | \value{ 15 | a numerical scalar 16 | } 17 | \description{ 18 | Efficiently computes \eqn{x' A x} - or in R-notation: 19 | } 20 | \details{ 21 | Length of \code{x} should equal the number of rows and columns of \code{A}. 22 | } 23 | \keyword{internal} 24 | -------------------------------------------------------------------------------- /man/ranova.Rd: -------------------------------------------------------------------------------- 1 | % Generated by roxygen2: do not edit by hand 2 | % Please edit documentation in R/ranova.R 3 | \name{ranova} 4 | \alias{ranova} 5 | \alias{rand} 6 | \title{ANOVA-Like Table for Random-Effects} 7 | \usage{ 8 | ranova(model, reduce.terms = TRUE, ...) 9 | 10 | rand(model, reduce.terms = TRUE, ...) 11 | } 12 | \arguments{ 13 | \item{model}{a linear mixed effect model fitted with \code{lmer()} 14 | (inheriting from class \code{lmerMod}).} 15 | 16 | \item{reduce.terms}{if \code{TRUE} (default) random-effect terms are 17 | reduced (if possible). If \code{FALSE} random-effect terms are simply 18 | removed.} 19 | 20 | \item{...}{currently ignored} 21 | } 22 | \value{ 23 | an ANOVA-like table with single term deletions of random-effects 24 | inheriting from class \code{anova} and \code{data.frame} with the columns: 25 | \item{npar}{number of model parameters.} 26 | \item{logLik}{the log-likelihood for the model. Note that this is the 27 | REML-logLik if the model is fitted with REML.} 28 | \item{AIC}{the AIC for the model evaluated as \code{-2*(logLik - npar)}. 29 | Smaller is better.} 30 | \item{LRT}{the likelihood ratio test statistic; twice the difference in 31 | log-likelihood, which is asymptotically chi-square distributed.} 32 | \item{Df}{degrees of freedom for the likelihood ratio test: the difference in 33 | number of model parameters.} 34 | \item{Pr(>Chisq)}{the p-value.} 35 | } 36 | \description{ 37 | Compute an ANOVA-like table with tests of random-effect terms in the model. 38 | Each random-effect term is reduced or removed and likelihood ratio tests of 39 | model reductions are presented in a form similar to that of 40 | \code{\link[=drop1.lmerModLmerTest]{drop1}}. 41 | \code{rand} is an alias for \code{ranova}. 42 | } 43 | \details{ 44 | If the model is fitted with REML the tests are REML-likelihood ratio tests. 45 | 46 | A random-effect term of the form \code{(f1 + f2 | gr)} is reduced to 47 | terms of the form \code{(f2 | gr)} and \code{(f1 | gr)} and these reduced 48 | models are compared to the original model. 49 | If \code{reduce.terms} is \code{FALSE} \code{(f1 + f2 | gr)} is removed 50 | instead. 51 | 52 | A random-effect term of the form \code{(f1 | gr)} is reduced to \code{(1 | gr)} 53 | (unless \code{reduce.terms} is \code{FALSE}). 54 | 55 | A random-effect term of the form \code{(1 | gr)} is not reduced but 56 | simply removed. 57 | 58 | A random-effect term of the form \code{(0 + f1 | gr)} or \code{(-1 + f1 | gr)} 59 | is reduced (if \code{reduce.terms = TRUE}) to \code{(1 | gr)}. 60 | 61 | A random-effect term of the form \code{(1 | gr1/gr2)} is automatically 62 | expanded to two terms: \code{(1 | gr2:gr1)} and \code{(1 | gr1)} using 63 | \code{\link[lme4]{findbars}}. 64 | 65 | In this exposition it is immaterial whether \code{f1} and \code{f2} are 66 | factors or continuous variables. 67 | } 68 | \note{ 69 | Note that \code{anova} can be used to compare two models and will often 70 | be able to produce the same tests as \code{ranova}. This is, however, not always the 71 | case as illustrated in the examples. 72 | } 73 | \section{Warning}{ 74 | 75 | In certain cases tests of non-nested models may be generated. An example 76 | is when \code{(0 + poly(x, 2) | gr)} is reduced (the default) to \code{(1 | gr)}. 77 | To our best knowledge non-nested model comparisons are only generated in 78 | cases which are statistical nonsense anyway (such as in this example where 79 | the random intercept is suppressed). 80 | } 81 | 82 | \examples{ 83 | 84 | # Test reduction of (Days | Subject) to (1 | Subject): 85 | fm1 <- lmer(Reaction ~ Days + (Days|Subject), sleepstudy) 86 | ranova(fm1) # 2 df test 87 | 88 | # This test can also be achieved with anova(): 89 | fm2 <- lmer(Reaction ~ Days + (1|Subject), sleepstudy) 90 | anova(fm1, fm2, refit=FALSE) 91 | 92 | # Illustrate reduce.test argument: 93 | # Test removal of (Days | Subject): 94 | ranova(fm1, reduce.terms = FALSE) # 3 df test 95 | 96 | # The likelihood ratio test statistic is in this case: 97 | fm3 <- lm(Reaction ~ Days, sleepstudy) 98 | 2*c(logLik(fm1, REML=TRUE) - logLik(fm3, REML=TRUE)) # LRT 99 | 100 | # anova() is not always able to perform the same tests as ranova(), 101 | # for example: 102 | anova(fm1, fm3, refit=FALSE) # compares REML with ML and should not be used 103 | anova(fm1, fm3, refit=TRUE) # is a test of ML fits and not what we seek 104 | 105 | # Also note that the lmer-fit needs to come first - not an lm-fit: 106 | # anova(fm3, fm1) # does not work and gives an error 107 | 108 | # ranova() may not generate all relevant test: 109 | # For the following model ranova() indicates that we should not reduce 110 | # (TVset | Assessor): 111 | fm <- lmer(Coloursaturation ~ TVset * Picture + (TVset | Assessor), data=TVbo) 112 | ranova(fm) 113 | # However, a more appropriate model is: 114 | fm2 <- lmer(Coloursaturation ~ TVset * Picture + (1 | TVset:Assessor), data=TVbo) 115 | anova(fm, fm2, refit=FALSE) 116 | # fm and fm2 has essentially the same fit to data but fm uses 5 parameters 117 | # more than fm. 118 | 119 | } 120 | \seealso{ 121 | \code{\link[=drop1.lmerModLmerTest]{drop1}} for tests of marginal 122 | fixed-effect terms and 123 | \code{\link{anova}} for usual anova tables for fixed-effect terms. 124 | } 125 | \author{ 126 | Rune Haubo B. Christensen and Alexandra Kuznetsova 127 | } 128 | -------------------------------------------------------------------------------- /man/rbindall.Rd: -------------------------------------------------------------------------------- 1 | % Generated by roxygen2: do not edit by hand 2 | % Please edit documentation in R/utils.R 3 | \name{rbindall} 4 | \alias{rbindall} 5 | \title{\code{rbind} Multiple Objects} 6 | \usage{ 7 | rbindall(...) 8 | } 9 | \arguments{ 10 | \item{...}{objects to be \code{rbind}'ed - typically matrices or vectors} 11 | } 12 | \description{ 13 | \code{rbind} Multiple Objects 14 | } 15 | \keyword{internal} 16 | -------------------------------------------------------------------------------- /man/rm_complete_terms.Rd: -------------------------------------------------------------------------------- 1 | % Generated by roxygen2: do not edit by hand 2 | % Please edit documentation in R/ranova.R 3 | \name{rm_complete_terms} 4 | \alias{rm_complete_terms} 5 | \title{Remove Terms from Formula} 6 | \usage{ 7 | rm_complete_terms(terms, full_formula, random = TRUE) 8 | } 9 | \arguments{ 10 | \item{terms}{character vector (or list) of terms to remove from 11 | \code{full_formula}} 12 | 13 | \item{full_formula}{formula} 14 | 15 | \item{random}{if \code{TRUE} names of the return list have parentheses around 16 | them.} 17 | } 18 | \description{ 19 | Remove fixef or ranef terms from formula, return a list of modified formulae 20 | with environment restored to that of the original formula. 21 | } 22 | \keyword{internal} 23 | -------------------------------------------------------------------------------- /man/show_tests.Rd: -------------------------------------------------------------------------------- 1 | % Generated by roxygen2: do not edit by hand 2 | % Please edit documentation in R/lmer_anova.R 3 | \name{show_tests} 4 | \alias{show_tests} 5 | \alias{show_tests.default} 6 | \title{Show Tests Generic Function and Default Method} 7 | \usage{ 8 | show_tests(object, ...) 9 | 10 | \method{show_tests}{default}(object, fractions = FALSE, names = TRUE, ...) 11 | } 12 | \arguments{ 13 | \item{object}{a suitable object with an \code{"hypotheses"} attribute, e.g. an 14 | anova table or an \code{ls_means} table as defined in \pkg{lmerTest}.} 15 | 16 | \item{...}{parsed on to methods; currently not used in the default method.} 17 | 18 | \item{fractions}{display entries in the hypothesis matrices as fractions?} 19 | 20 | \item{names}{if \code{FALSE} column and row names of the hypothesis matrices 21 | are suppressed.} 22 | } 23 | \description{ 24 | Show Tests Generic Function and Default Method 25 | } 26 | \seealso{ 27 | \code{\link{show_tests.anova}} and \code{\link{show_tests.ls_means}} 28 | } 29 | \author{ 30 | Rune Haubo B. Christensen 31 | 32 | Rune Haubo B. Christensen 33 | } 34 | \keyword{internal} 35 | -------------------------------------------------------------------------------- /man/show_tests.anova.Rd: -------------------------------------------------------------------------------- 1 | % Generated by roxygen2: do not edit by hand 2 | % Please edit documentation in R/lmer_anova.R 3 | \name{show_tests.anova} 4 | \alias{show_tests.anova} 5 | \title{Show Hypothesis Tests in ANOVA Tables} 6 | \usage{ 7 | \method{show_tests}{anova}(object, fractions = FALSE, names = TRUE, ...) 8 | } 9 | \arguments{ 10 | \item{object}{an anova table with a \code{"hypotheses"} attribute.} 11 | 12 | \item{fractions}{display entries in the hypothesis matrices as fractions?} 13 | 14 | \item{names}{if \code{FALSE} column and row names of the hypothesis matrices 15 | are suppressed.} 16 | 17 | \item{...}{currently not used.} 18 | } 19 | \value{ 20 | a list of hypothesis matrices. 21 | } 22 | \description{ 23 | Extracts hypothesis matrices for terms in ANOVA tables detailing exactly which 24 | functions of the parameters are being tested in anova tables. 25 | } 26 | \examples{ 27 | 28 | # Fit basic model to the 'cake' data: 29 | data("cake", package="lme4") 30 | fm1 <- lmer(angle ~ recipe * temp + (1|recipe:replicate), cake) 31 | 32 | # Type 3 anova table: 33 | (an <- anova(fm1, type="3")) 34 | 35 | # Display tests/hypotheses for type 1, 2, and 3 ANOVA tables: 36 | # (and illustrate effects of 'fractions' and 'names' arguments) 37 | show_tests(anova(fm1, type="1")) 38 | show_tests(anova(fm1, type="2"), fractions=TRUE, names=FALSE) 39 | show_tests(an, fractions=TRUE) 40 | 41 | } 42 | \seealso{ 43 | \code{\link[=show_tests.ls_means]{show_tests}} for \code{ls_means} 44 | objects. 45 | } 46 | \author{ 47 | Rune Haubo B. Christensen 48 | } 49 | -------------------------------------------------------------------------------- /man/show_tests.ls_means.Rd: -------------------------------------------------------------------------------- 1 | % Generated by roxygen2: do not edit by hand 2 | % Please edit documentation in R/ls_means.R 3 | \name{show_tests.ls_means} 4 | \alias{show_tests.ls_means} 5 | \title{Show LS-means Hypothesis Tests and Contrasts} 6 | \usage{ 7 | \method{show_tests}{ls_means}(object, fractions = FALSE, names = TRUE, ...) 8 | } 9 | \arguments{ 10 | \item{object}{an \code{ls_means} object.} 11 | 12 | \item{fractions}{display contrasts as fractions rather than decimal numbers?} 13 | 14 | \item{names}{include row and column names of the contrasts matrices?} 15 | 16 | \item{...}{currently not used.} 17 | } 18 | \value{ 19 | a list of contrast matrices; one matrix for each model term. 20 | } 21 | \description{ 22 | Extracts the contrasts which defines the LS-mean hypothesis tests. 23 | } 24 | \examples{ 25 | 26 | data("cake", package="lme4") 27 | model <- lmer(angle ~ recipe * temp + (1|recipe:replicate), cake) 28 | 29 | # LS-means: 30 | (lsm <- ls_means(model)) 31 | 32 | # Contrasts for LS-means estimates and hypothesis tests: 33 | show_tests(lsm) 34 | 35 | } 36 | \seealso{ 37 | \code{\link[=ls_means.lmerModLmerTest]{ls_means}} for computation of 38 | LS-means and \code{\link[=show_tests.anova]{show_tests}} for \code{anova} 39 | objects. 40 | } 41 | \author{ 42 | Rune Haubo B. Christensen 43 | } 44 | -------------------------------------------------------------------------------- /man/single_anova.Rd: -------------------------------------------------------------------------------- 1 | % Generated by roxygen2: do not edit by hand 2 | % Please edit documentation in R/lmer_anova.R 3 | \name{single_anova} 4 | \alias{single_anova} 5 | \title{ANOVA Tables for Linear Mixed Models} 6 | \usage{ 7 | single_anova( 8 | object, 9 | type = c("III", "II", "I", "3", "2", "1", "yates", "marginal", "2b"), 10 | ddf = c("Satterthwaite", "Kenward-Roger") 11 | ) 12 | } 13 | \arguments{ 14 | \item{object}{an \code{lmerModLmerTest} object; the result of \code{lmer()} 15 | after loading the \pkg{lmerTest}-package.} 16 | 17 | \item{type}{the type of ANOVA table requested (using the SAS terminology for 18 | these) with Type I being the familiar sequential ANOVA table.} 19 | 20 | \item{ddf}{method for computing denominator degrees of freedom.} 21 | } 22 | \value{ 23 | an ANOVA table 24 | } 25 | \description{ 26 | ANOVA Tables for Linear Mixed Models 27 | } 28 | \author{ 29 | Rune Haubo B. Christensen 30 | } 31 | \keyword{internal} 32 | -------------------------------------------------------------------------------- /man/step.Rd: -------------------------------------------------------------------------------- 1 | % Generated by roxygen2: do not edit by hand 2 | % Please edit documentation in R/step.R 3 | \name{step} 4 | \alias{step} 5 | \alias{step.default} 6 | \title{Generic Step Function} 7 | \usage{ 8 | step(object, ...) 9 | 10 | \method{step}{default}(object, ...) 11 | } 12 | \arguments{ 13 | \item{object}{a model object.} 14 | 15 | \item{...}{currently not used.} 16 | } 17 | \description{ 18 | Generic step function with default method \code{stats::step}. This 19 | construction ensures that \code{stats::step} still works on \code{lm} 20 | objects etc. after loading the \pkg{lmerTest} package. 21 | } 22 | \seealso{ 23 | \code{\link[=step.lmerModLmerTest]{step}} 24 | } 25 | \author{ 26 | Rune Haubo B. Christensen 27 | } 28 | \keyword{internal} 29 | -------------------------------------------------------------------------------- /man/step.lmerModLmerTest.Rd: -------------------------------------------------------------------------------- 1 | % Generated by roxygen2: do not edit by hand 2 | % Please edit documentation in R/step.R 3 | \name{step.lmerModLmerTest} 4 | \alias{step.lmerModLmerTest} 5 | \alias{get_model.step_list} 6 | \title{Backward Elimination for Linear Mixed Models} 7 | \usage{ 8 | \method{step}{lmerModLmerTest}( 9 | object, 10 | ddf = c("Satterthwaite", "Kenward-Roger"), 11 | alpha.random = 0.1, 12 | alpha.fixed = 0.05, 13 | reduce.fixed = TRUE, 14 | reduce.random = TRUE, 15 | keep, 16 | ... 17 | ) 18 | 19 | \method{get_model}{step_list}(x, ...) 20 | } 21 | \arguments{ 22 | \item{object}{a fitted model object. For the \code{lmerModLmerTest} method 23 | an \code{\link{lmer}} model fit (of class \code{"lmerModLmerTest"}.)} 24 | 25 | \item{ddf}{the method for computing the denominator degrees of freedom and 26 | F-statistics. \code{ddf="Satterthwaite"} (default) uses Satterthwaite's method; 27 | \code{ddf="Kenward-Roger"} uses Kenward-Roger's method.} 28 | 29 | \item{alpha.random}{alpha for random effects elimination} 30 | 31 | \item{alpha.fixed}{alpha for fixed effects elimination} 32 | 33 | \item{reduce.fixed}{reduce fixed effect structure? \code{TRUE} by default.} 34 | 35 | \item{reduce.random}{reduce random effect structure? \code{TRUE} by default.} 36 | 37 | \item{keep}{an optional character vector of fixed effect terms which should 38 | not be considered for eliminated. Valid terms are given by 39 | \code{attr(terms(object), "term.labels")}. Terms that are marginal to terms 40 | in keep will also not be considered for eliminations.} 41 | 42 | \item{...}{currently not used.} 43 | 44 | \item{x}{a step object.} 45 | } 46 | \value{ 47 | \code{step} returns a list with elements \code{"random"} and 48 | \code{"fixed"} each 49 | containing anova-like elimination tables. The \code{"fixed"} table is 50 | based on \code{drop1} and the \code{"random"} table is 51 | based on \code{ranova} (a \code{drop1}-like table for random effects). Both 52 | tables have a column \code{"Eliminated"} indicating the order in which terms 53 | are eliminated from the model with zero (\code{0}) indicating that the term 54 | is not eliminated from the model. 55 | 56 | The \code{step} object also contains the final model as an attribute which 57 | is extractable with \code{get_model()}. 58 | } 59 | \description{ 60 | Backward elimination of random-effect terms followed by backward elimination 61 | of fixed-effect terms in linear mixed models. 62 | } 63 | \details{ 64 | Tests of random-effects are performed using \code{\link{ranova}} (using 65 | \code{reduce.terms = TRUE}) and tests of fixed-effects are performed using 66 | \code{\link[=drop1.lmerModLmerTest]{drop1}}. 67 | 68 | The step method for \code{\link{lmer}} fits has a print method. 69 | } 70 | \examples{ 71 | 72 | # Fit a model to the ham dataset: 73 | fm <- lmer(Informed.liking ~ Product*Information+ 74 | (1|Consumer) + (1|Product:Consumer) 75 | + (1|Information:Consumer), data=ham) 76 | 77 | # Backward elimination using terms with default alpha-levels: 78 | (step_res <- step(fm)) 79 | final <- get_model(step_res) 80 | anova(final) 81 | 82 | \dontrun{ 83 | # Fit 'big' model: 84 | fm <- lmer(Informed.liking ~ Product*Information*Gender*Age + 85 | + (1|Consumer) + (1|Consumer:Product) + 86 | (1|Consumer:Information), data=ham) 87 | step_fm <- step(fm) 88 | step_fm # Display elimination results 89 | final_fm <- get_model(step_fm) 90 | } 91 | 92 | } 93 | \seealso{ 94 | \code{\link[=drop1.lmerModLmerTest]{drop1}} for tests of marginal 95 | fixed-effect terms and \code{\link{ranova}} for a 96 | \code{\link[=drop1.lmerModLmerTest]{drop1}}-like table of reduction of 97 | random-effect terms. 98 | } 99 | \author{ 100 | Rune Haubo B. Christensen and Alexandra Kuznetsova 101 | } 102 | -------------------------------------------------------------------------------- /man/summary.lmerModLmerTest.Rd: -------------------------------------------------------------------------------- 1 | % Generated by roxygen2: do not edit by hand 2 | % Please edit documentation in R/lmer_summary.R 3 | \name{summary.lmerModLmerTest} 4 | \alias{summary.lmerModLmerTest} 5 | \title{Summary Method for Linear Mixed Models} 6 | \usage{ 7 | \method{summary}{lmerModLmerTest}(object, ..., ddf = c("Satterthwaite", "Kenward-Roger", "lme4")) 8 | } 9 | \arguments{ 10 | \item{object}{an lmerModLmerTest object.} 11 | 12 | \item{...}{additional arguments passed on to \code{lme4::summary.merMod}} 13 | 14 | \item{ddf}{the method for computing the degrees of freedom and 15 | t-statistics. \code{ddf="Satterthwaite"} (default) uses Satterthwaite's method; 16 | \code{ddf="Kenward-Roger"} uses Kenward-Roger's method, 17 | \code{ddf = "lme4"} returns the lme4-summary i.e., using the summary 18 | method for \code{lmerMod} objects as defined in the \pkg{lme4}-package and 19 | ignores the \code{type} argument. Partial matching is allowed.} 20 | } 21 | \value{ 22 | A summary object with a coefficient table (a \code{matrix}) including 23 | t-values and p-values. The coefficient table can be extracted with 24 | \code{coef(summary())}. 25 | } 26 | \description{ 27 | Summaries of Linear Mixed Models with coefficient tables including t-tests 28 | and p-values using Satterthwaites's or Kenward-Roger's methods for 29 | degrees-of-freedom and t-statistics. 30 | } 31 | \details{ 32 | The returned object is of class 33 | \code{c("summary.lmerModLmerTest", "summary.merMod")} utilizing \code{print}, 34 | \code{coef} and other methods defined for \code{summary.merMod} objects. 35 | The \code{"Kenward-Roger"} method use methods from the \pkg{pbkrtest} package internally 36 | to compute t-statistics and associated degrees-of-freedom. 37 | } 38 | \examples{ 39 | 40 | # Fit example model: 41 | data("sleepstudy", package="lme4") 42 | fm <- lmer(Reaction ~ Days + (1|Subject) + (0+Days|Subject), sleepstudy) 43 | 44 | # Get model summary: 45 | summary(fm) # Satterthwaite df and t-tests 46 | 47 | # Extract coefficient table: 48 | coef(summary(fm)) 49 | 50 | # Use the Kenward-Roger method 51 | if(requireNamespace("pbkrtest", quietly = TRUE)) 52 | summary(fm, ddf="Kenward-Roger") 53 | 54 | # The lme4-summary table: 55 | summary(fm, ddf="lme4") # same as summary(as(fm, "lmerMod")) 56 | 57 | \dontshow{ 58 | # Check that summaries are as expected: 59 | summ_fm <- coef(summary(fm)) 60 | summ_fm_lme4 <- coef(summary(fm, ddf="lme4")) 61 | stopifnot( 62 | all(colnames(summ_fm) == c("Estimate", "Std. Error", "df", "t value", "Pr(>|t|)")), 63 | all(colnames(summ_fm_lme4) == c("Estimate", "Std. Error", "t value")), 64 | all(!(is.na(summ_fm))), 65 | all(!(is.na(summ_fm_lme4))) 66 | ) 67 | if(requireNamespace("pbkrtest", quietly = TRUE) && getRversion() >= "3.3.3") { 68 | summ_fm_kr <- coef(summary(fm, ddf="Kenward-Roger")) 69 | stopifnot( 70 | all(colnames(summ_fm_kr) == c("Estimate", "Std. Error", "df", "t value", "Pr(>|t|)")), 71 | all(!(is.na(summ_fm_kr))) 72 | ) 73 | } 74 | } 75 | } 76 | \seealso{ 77 | \code{\link{contest1D}} for one degree-of-freedom contrast tests 78 | and \code{\link[pbkrtest]{KRmodcomp}} for Kenward-Roger F-tests. 79 | } 80 | \author{ 81 | Rune Haubo B. Christensen and Alexandra Kuznetsova 82 | } 83 | -------------------------------------------------------------------------------- /man/term_contain.Rd: -------------------------------------------------------------------------------- 1 | % Generated by roxygen2: do not edit by hand 2 | % Please edit documentation in R/contrast_utils.R 3 | \name{term_contain} 4 | \alias{term_contain} 5 | \title{Determine which Terms Contain a Term} 6 | \usage{ 7 | term_contain(term, factors, dataClasses, term_names) 8 | } 9 | \arguments{ 10 | \item{term}{character; name of a model term and one of \code{term_names}.} 11 | 12 | \item{factors}{the result of \code{attr(terms_object, "factors")}.} 13 | 14 | \item{dataClasses}{the result of 15 | \code{attr(terms(model, fixed.only=FALSE), "dataClasses")}. Note that 16 | \code{fixed.only=FALSE} is only needed for \code{merMod} objects, but does 17 | no harm for \code{lm} objects.} 18 | 19 | \item{term_names}{the result of \code{attr(terms_object, "term.labels")}.} 20 | } 21 | \value{ 22 | a logical vector indicating for each term in \code{term_names} if 23 | it contains \code{term}. 24 | } 25 | \description{ 26 | The definition of \emph{containment} follows from the SAS documentation on 27 | "The Four Types of Estimable Functions". 28 | } 29 | \details{ 30 | Containment is defined for two model terms, say, F1 and F2 as: 31 | F1 is contained in F2 (F2 contains F1) if 32 | \enumerate{ 33 | \item F1 and F2 involve the same continuous variables (if any) 34 | \item F2 involve more factors than F1 35 | \item All factors in F1 (if any) are part of F2 36 | } 37 | The intercept, though not really a model term, is defined by SAS to be 38 | contained in all factor terms, but it is not contained in any 39 | effect involving a continuous variable. 40 | } 41 | \keyword{internal} 42 | -------------------------------------------------------------------------------- /misc/copyright_header.txt: -------------------------------------------------------------------------------- 1 | ############################################################################# 2 | # Copyright (c) 2013-2020 Alexandra Kuznetsova, Per Bruun Brockhoff, and 3 | # Rune Haubo Bojesen Christensen 4 | # 5 | # This file is part of the lmerTest package for R (*lmerTest*) 6 | # 7 | # *lmerTest* is free software: you can redistribute it and/or modify 8 | # it under the terms of the GNU General Public License as published by 9 | # the Free Software Foundation, either version 2 of the License, or 10 | # (at your option) any later version. 11 | # 12 | # *lmerTest* is distributed in the hope that it will be useful, 13 | # but WITHOUT ANY WARRANTY; without even the implied warranty of 14 | # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 15 | # GNU General Public License for more details. 16 | # 17 | # A copy of the GNU General Public License is available at 18 | # and/or 19 | # . 20 | ############################################################################# 21 | -------------------------------------------------------------------------------- /misc/modify_copyright_header.R: -------------------------------------------------------------------------------- 1 | 2 | ######################################################## 3 | ## Change or modify copyright header in R-files: 4 | 5 | cp_header <- readLines("~/GitHub/lmerTestR/package/misc/copyright_header.txt") 6 | 7 | folder <- "~/GitHub/lmerTestR/package/R" 8 | filenames <- list.files(folder) 9 | 10 | # fn <- filenames[1] # for tests 11 | for(fn in filenames) { 12 | filepath <- paste(folder, fn, sep="/") 13 | txt <- readLines(filepath) 14 | # Get index of copyright header first and last line: 15 | ind <- grep("^########################################", txt) 16 | # Check if copyright header exists in file: 17 | if(grepl("Copyright (c)", txt[ind[1]+1], fixed=TRUE)) { 18 | txt <- txt[-seq_len(ind[2])] # remove copyright header 19 | txt <- c(cp_header, txt) # add new copyright header 20 | writeLines(txt, con=filepath) # write to file 21 | } else { 22 | warning(sprintf("No copyright header found in file: %s.", fn)) 23 | } 24 | } 25 | 26 | ######################################################## 27 | # Write copyright header to new file: 28 | # 29 | # for(fn in filenames) { 30 | # filepath <- paste(folder, fn, sep="/") 31 | # txt <- readLines(filepath) 32 | # writeLines(c(cp_header, txt), con=filepath) 33 | # } 34 | 35 | ######################################################## 36 | -------------------------------------------------------------------------------- /pkg_notes/Satterthwaite_for_LMMs.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/runehaubo/lmerTestR/35dc5885205d709cdc395b369b08ca2b7273cb78/pkg_notes/Satterthwaite_for_LMMs.pdf -------------------------------------------------------------------------------- /pkg_notes/implementation.Rmd: -------------------------------------------------------------------------------- 1 | --- 2 | title: "Implementation in package lmerTestR" 3 | author: "Rune Haubo B Christensen" 4 | date: "`r Sys.Date()`" 5 | output: 6 | html_document: 7 | toc: TRUE 8 | --- 9 | 10 | ```{r setup, include=FALSE} 11 | knitr::opts_chunk$set(echo = TRUE) 12 | ``` 13 | 14 | ## `lmer` fitting linear mixed models 15 | 16 | **lmerTestR** overloads `lmer` from **lme4** in order to facilitate the computation of summary tables, anova tabels and tests of costum contrasts with $t$ and $F$ tests using the Satterthwaite method for computation of denominator degrees of freedom. 17 | 18 | 1. `lmerTestR::lmer` produces an object of class `lmerModLmerTest` extending class `lmerMod` (as produced by `lme4::lmer`) 19 | 1. `lmerTestR::lmer` adds slots containing the covariance matrix of the variance-covariance parameters in the model and the gradient of the covariance matrix of the fixed effect parameters, $\beta$ (and a few other things) which are required for the computation of Satterthwaite degrees of freedom. 20 | 1. The covariance matrix of the variance-covariance parameters in the model and the gradient of the covariance matrix of the fixed effect parameters are computed numerically using `hessian` and `jacobian` functions from the **numDeriv** package utilizing the accurate Richardson extrapolation method. 21 | 22 | ## Satterthwaite's method for denominator degrees of freedom 23 | 24 | Satterthwaite's method is implemented for one-df contrasts as well as for multi-df contrasts in two functions respectively: 25 | 26 | 1. `contest1D` takes a contrast-vector (or 1D row-matrix) and produces a `data.frame` with $t$-tests in the form similar to a summary coefficient table. This function is used by the `summary` method for `lmer` fits to compute the $p$-values for $t$-tests of the model coefficients. 27 | 1. `contestMD` takes a contrast-matrix (or a vector) and produces a `data.frame` with sums of squares, mean squares, $F$-values, numerator and denominator degrees of freedom and $p$-values in a form similar to that of an ANOVA table. This function is used by the `anova` method for `lmer` fits. 28 | 29 | The computations involved in the Satterthwaite's method are described in a separate document/vignette. 30 | 31 | ## Kenward-Roger's (KR) method 32 | 33 | 1. The KR method is facilitated via the implementation in the **pbkrtest** package (**lmerTestR** _suggests_ this package) 34 | 1. The KR method not only involves an estimate of the denominator df (as does the Satterthwaite method) but also an adjusted covariance matrix of $\beta$ as well as a scaling of the $F$-statistic. 35 | 1. In simple cases the adjusted covariance matrix of $\beta$ equals the standard one and scaling of the $F$-statistics may be neutral. 36 | 1. As a consequence of the adjusted covariance matrix of fixed effect parameters, the standard errors and $t$-values of model coefficients (as in `summary` tables) may be respectively larger and smaller. 37 | 1. The potential scaling applied to $F$-statistics is not applied to $t$-statistics. (I am not sure if $F$-tests on one numerator df will never be scaled -- that may be the case.) 38 | 1. The KR $t$-tests are implemented by computing the adjusted covariance matrix of the fixed effect parameters with `pbkrtest::vcovAdj` and the KR df with `pbkrtest::Lb_ddf`. Computing the KR $t$-tests for a whole set of one-df contrasts (as in a summary table) therefore only involves calculating the adjusted covariance matrix once. 39 | 1. The KR $F$-tests are implemented by passing a contrast matrix to `pbkrtest::KRmodcomp`. When computing $F$-tests for a series of terms (as is done in ANOVA tables) `pbkrtest::KRmodcomp` is called multiple times in each case evaluating the same adjusted covariance matrix of $\beta$ (the computationally time consuming part). We have not found a way to decompose the computations in `pbkrtest::KRmodcomp` so that `pbkrtest::vcovAdj` could be called just once instead. The culprit is the calculation of the scaling of the $F$-value for which **pbkrtest** does not appear to export a low-level (direct) method. 40 | 1. The KR-method is not available for ML-fits and attempts to use ML-fits causes functions in **lmerTestR** to throw an error. 41 | 42 | ## ANOVA tables using the `anova` method 43 | 44 | 1. Produces an ANOVA table if called with a single model as argument - the internal function `single_anova` handles this. 45 | 1. Produces a comparison of models if more than one model is passed to `anova`. This is not implemented in **lmerTestR**; `callNextMethod` is applied. 46 | 1. `single_anova` computes the appropriate contrast matrices (corresponding to type I, II, or III ANOVA tables) and then uses `contestMD` to compute the relevant SSQ, MS, $F$-values etc. 47 | 48 | ### Type I ANOVA tables 49 | 50 | 1. The type I (sequential) ANOVA contrasts are produced by `get_contrasts_type1` which forms the contrasts using the Doolittle decomposition of $X^\top X$ where $X$ is the standard full-rank (column rank) design matrix. 51 | 52 | 53 | ### Type II ANOVA tables 54 | 55 | 1. Not yet implemented 56 | 57 | 58 | ### Type III ANOVA tables 59 | 60 | 1. Type III ANOVA contrasts are produces by `get_contrasts_type3` which uses a SAS-type algorithm based on the 'full' rank-deficient design matrix (produced by `get_rdX`) and a 'general' contrast matrix 'L' (produced by `general_L`). 61 | 1. The algorithm only works when the standard `contr.treatment` or `contr.SAS` is used for coding of factors in the design matrix. Using other "contrasts", for example `contr.sum` or `contr.poly`, which is used by default for ordered factors produces an error. 62 | 63 | 64 | ## The `summary` method for `lmer` model fits 65 | 66 | The summary method does two things to a `lme4::lmer` summary table before it is returned. The `lme4::print.summary.merMod` print method takes care of printing. 67 | 68 | 1. The summary method appends a title to model fit describing which method was used for $t$-tests: Satterthwaite or Kenward-Roger 69 | 1. The summary method computes the coefficient table with (denominator) degrees of freedom and $p$-values for the $t$-statistics by passing the rows of a unit-diagonal matrix with as many rows as there are coefficients to `contest1D`. 70 | 71 | 72 | 73 | 74 | 75 | -------------------------------------------------------------------------------- /pkg_notes/implementation_notes.Rmd: -------------------------------------------------------------------------------- 1 | --- 2 | title: "Notes on the implementation in lmerTest and lmerTestR" 3 | author: "Rune Haubo B Christensen" 4 | date: "`r Sys.Date()`" 5 | output: 6 | html_document: 7 | toc: TRUE 8 | --- 9 | 10 | ```{r setup, include=FALSE} 11 | knitr::opts_chunk$set(echo = TRUE) 12 | ``` 13 | 14 | # On the the use of `contr.SAS` in **lmerTest** 15 | 16 | When computing type III ANOVA tables, **lmerTest** refits the model using `contr.SAS`, i.e., SAS-type contrasts for all factors. This has the following consequences: 17 | 18 | Draw backs: 19 | 20 | 1. The same model has to be refit once more thus wasting time and computational recourses. 21 | 1. The coding of ordered factors is changed from `contr.poly` to `contr.SAS`. What is the meaning of type III tests for ordered factors? How does SAS handle these? 22 | 1. There could be cases where the numerical behaviour of the models differ when SAS contrasts are used. For example the model might not converge proporly after changing to SAS contrasts. 23 | 24 | Advantages: 25 | 26 | 1. Irrespective of the contrasts used, type III tests for all terms are produced. This obviously includes the usual `contr.treatment` but also `contr.sum`, `contr.helmert` and `contr.poly` which generates orthogonal polynomials for ordered factors. 27 | 1. Whether `contr.treatment` or `contr.SAS` are used usually does not matter - only the interpretation of coefficients (which are never seen anyway) changes. 28 | 1. The `L`-matrix (containing the general contrast structure) has a particular and known structure. 29 | 30 | Notes: 31 | 32 | 1. It seems that even though models are refitted with `contr.SAS`, that the code also works when `contr.treatment` is used. This means that when the default `contr.treatment` have been used, there should be no reason to refit the models with `contr.SAS`. 33 | 34 | **lmerTestR** takes a different approach since it doesn't refit the models and so throws an error if `contr.treatment` or `contr.SAS` has not been used. Essentially this requires the user to refit the models with one of these contrasts. This will probably rarely be the case, but can come into play if `contr.sum` has been set for some odd reason, or if ordered factors are used in which case `contr.poly` will be used by default. 35 | 36 | -------------------------------------------------------------------------------- /pkg_notes/new_lmerTest.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/runehaubo/lmerTestR/35dc5885205d709cdc395b369b08ca2b7273cb78/pkg_notes/new_lmerTest.pdf -------------------------------------------------------------------------------- /pkg_notes/view_html.md: -------------------------------------------------------------------------------- 1 | To view htlm-files in browser, use: 2 | 3 | 4 | 5 | or directly prepend as in the following links: 6 | 7 | 1. 8 | 1. 9 | 1. 10 | -------------------------------------------------------------------------------- /tests/test_a_utils.R: -------------------------------------------------------------------------------- 1 | # test_a_utils.R 2 | 3 | library(lmerTest) 4 | 5 | # test safeDeparse() - equivalence and differences to deparse(): 6 | deparse_args <- formals(deparse) 7 | safeDeparse_args <- formals(lmerTest:::safeDeparse) 8 | stopifnot( 9 | all.equal(names(deparse_args), names(safeDeparse_args)), 10 | all.equal(deparse_args[!names(deparse_args) %in% c("control", "width.cutoff")], 11 | safeDeparse_args[!names(safeDeparse_args) %in% c("control", "width.cutoff")]), 12 | all.equal(deparse_args[["width.cutoff"]], 60L), 13 | all(eval(safeDeparse_args[["control"]]) %in% eval(deparse_args[["control"]])), 14 | all.equal(safeDeparse_args[["width.cutoff"]], 500L) 15 | ) 16 | 17 | -------------------------------------------------------------------------------- /tests/test_compare_sas.R: -------------------------------------------------------------------------------- 1 | # test_compare_sas.R 2 | library(lmerTest) 3 | 4 | # WRE says "using if(requireNamespace("pkgname")) is preferred, if possible." 5 | # even in tests: 6 | assertError <- function(expr, ...) 7 | if(requireNamespace("tools")) tools::assertError(expr, ...) else invisible() 8 | assertWarning <- function(expr, ...) 9 | if(requireNamespace("tools")) tools::assertWarning(expr, ...) else invisible() 10 | 11 | ##################################################################### 12 | 13 | 14 | # Use contrasts to get particular estimates for the summary table: 15 | l <- list(Frequency="contr.SAS", Income="contr.SAS") 16 | m.carrots <- lmer(Preference ~ sens2*Frequency*Income 17 | +(1+sens2|Consumer), data=carrots, contrasts=l) 18 | an.m <- anova(m.carrots) 19 | 20 | TOL <- 1e-4 21 | TOL2 <- 1e-5 22 | # with 4 decimals should agree with SAS output 23 | # numbers before decimals should agree with SAS output 24 | stopifnot( 25 | all.equal(an.m[,"Pr(>F)"], 26 | c(2e-5, 0.15512, 0.06939, 0.08223, 0.52459, 0.03119, 0.48344), 27 | tolerance = TOL), 28 | all.equal(round(an.m$DenDF), c(83, 83, 83, 83, 83, 83, 83)) 29 | ) 30 | 31 | sm <- summary(m.carrots) 32 | stopifnot( 33 | isTRUE(all.equal(sm$coefficients[,"Pr(>|t|)"], 34 | c(1e-10, 0.005061, 0.6865554, 0.342613, 0.129157, 35 | 0.088231, 0.846000, 0.354472, 0.526318, 0.020646, 0.010188, 36 | 0.031242, 0.055356, 0.694689, 0.099382, 0.28547, 37 | 0.977774, 0.855653, 0.427737, 0.321086, 0.417465 , 0.204385, 0.784437, 38 | 0.681434, 0.106180, 0.149122, 0.390870, 0.273686), tolerance=TOL, 39 | check.attributes = FALSE)) 40 | ) 41 | 42 | # Takes too long to run: 43 | # if(requireNamespace("pbkrtest", quietly = TRUE)) { 44 | # sm.kr <- summary(m.carrots, ddf = "Kenward-Roger") 45 | # 46 | # ## coefficients for Sat and KR agree in this example 47 | # # cbind(sm$coefficients[,"Pr(>|t|)"], sm.kr$coefficients[,"Pr(>|t|)"]) 48 | # all.equal(sm$coefficients[,"Pr(>|t|)"], sm.kr$coefficients[,"Pr(>|t|)"], 49 | # tol=TOL) 50 | # } 51 | 52 | ################################################################################ 53 | ## checking lsmeans and difflsmeans 54 | ## compare with SAS output 55 | m <- lmer(Informed.liking ~ Product*Information*Gender 56 | + (1|Product:Consumer) + (1|Consumer) , data=ham) 57 | 58 | 59 | lsm <- lsmeansLT(m, which = "Product") 60 | # head(lsm) 61 | 62 | stopifnot( 63 | isTRUE(all.equal(lsm[, "Estimate"], c(5.8084, 5.1012, 6.0909, 5.9256), 64 | tol=TOL, check.attributes = FALSE)), 65 | isTRUE(all.equal(round(lsm[, "t value"], 2), c(24.93, 21.89, 26.14, 25.43), tolerance=TOL, 66 | check.attributes = FALSE)), 67 | isTRUE(all.equal(lsm[, "lower"], c(5.3499, 4.6428, 5.6324, 5.4672), tolerance=TOL, 68 | check.attributes = FALSE)), 69 | isTRUE(all.equal(lsm[, "upper"], c(6.2668, 5.5597, 6.5493, 6.3840), tolerance=TOL, 70 | check.attributes = FALSE)) 71 | ) 72 | 73 | ################################################################################ 74 | # Not actually 'hard-coded' tests versus SAS results... 75 | 76 | m.carrots <- lmer(Preference ~ 0 + sens2 + Homesize + 77 | (1+sens2 | Consumer), data=carrots, 78 | control=lmerControl(optimizer="bobyqa")) 79 | summary(m.carrots) 80 | 81 | (an.1 <- anova(m.carrots, type=1)) 82 | (an.3 <- anova(m.carrots)) 83 | (an.lme4 <- anova(m.carrots, ddf = "lme4")) # difference in SSQ MS and F-values 84 | # Is this a problem with lme4? 85 | # fm <- lm(Preference ~ 0 + sens2 + Homesize, data=carrots) 86 | # anova(fm) 87 | # coef(summary(fm)) 88 | # Here the F value is a little greater than the squared t-value (as expected) 89 | 90 | stopifnot(all.equal(an.1[, "F value"], c(56.5394, 4169.87), tolerance = TOL2), 91 | all.equal(an.3[, "F value"], c(54.8206, 4169.87), tolerance = TOL2)) 92 | 93 | 94 | ################################################################################ 95 | # Check exmaple from GLM SAS report 96 | 97 | ### example from the paper GLM SAS 101 report 98 | a <- factor(c(1,1,1,2,2,2,2,2,1,2)) 99 | b <- factor(c(1,1,2,1,2,2,2,2,2,1)) 100 | f=factor(c(1,2,1,2,1,2,1,2,1,2)) 101 | y <- c(12,14,11,20,17,23,35,46,15,16) 102 | dd <- data.frame(a=a, b=b, y=y, f=f) 103 | 104 | ## check type 2 is order independent 105 | model <- lmer(y ~ a*b + (1|f), data=dd) 106 | model2 <- lmer(y ~ b*a + (1|f), data=dd) 107 | (an <- anova(model, type=2)) 108 | (an2 <- anova(model2, type=2)) 109 | stopifnot( 110 | isTRUE(all.equal(an,an2[c(2,1,3),], check.attributes = FALSE, tolerance=TOL2)) 111 | ) 112 | 113 | ## check the results are the same as from SAS proc mixed 114 | stopifnot( 115 | isTRUE(all.equal(an[,"F value"], c(3.90131, 1.32753, 0.99565), tolerance=TOL2)) 116 | ) 117 | ################################################################################ 118 | ## Check type II and III anova tables versus SAS 119 | 120 | m.carrots <- lmer(Preference ~ sens2*Homesize 121 | +(1+sens2|Consumer), data=carrots) 122 | (ancar <- anova(m.carrots, type=2)) 123 | 124 | stopifnot( 125 | isTRUE(all.equal(ancar[,"F value"], c(54.8361, 5.16138, 1.03035), tolerance = TOL)) 126 | ) 127 | 128 | m <- lmer(Informed.liking ~ Product*Age 129 | + (1|Consumer) , data=ham) 130 | (an <- anova(m, type=2)) 131 | 132 | stopifnot( 133 | isTRUE(all.equal(an[,"F value"], c(2.48135, .005387, 1.48451), tolerance = TOL2)) 134 | ) 135 | 136 | 137 | fm <- lmer(Preference ~ sens2*Homesize*sens1 + (1|Product), 138 | data=carrots) 139 | (ant2 <- anova(fm, type=2)) 140 | (ant3 <- anova(fm, type=3)) 141 | 142 | stopifnot( 143 | isTRUE(all.equal(ant2[,"F value"], 144 | c(16.4842, 14.0010, .526076, 1.18144, 145 | .107570, .335177, 1.05946), tolerance = TOL)), 146 | isTRUE(all.equal(ant3[,"F value"], 147 | c(16.9140, 14.0010,.481148, 1.18144, 148 | .074201, .335177, 1.05946), tolerance = TOL)) 149 | ) 150 | 151 | ################################################################################ 152 | 153 | 154 | -------------------------------------------------------------------------------- /tests/test_contest1D.R: -------------------------------------------------------------------------------- 1 | # test_contest1D.R 2 | library(lmerTest) 3 | 4 | # WRE says "using if(requireNamespace("pkgname")) is preferred, if possible." 5 | # even in tests: 6 | assertError <- function(expr, ...) 7 | if(requireNamespace("tools")) tools::assertError(expr, ...) else invisible() 8 | assertWarning <- function(expr, ...) 9 | if(requireNamespace("tools")) tools::assertWarning(expr, ...) else invisible() 10 | 11 | TOL <- 1e-4 12 | # Kenward-Roger only available with pbkrtest and only then validated in R >= 3.3.3 13 | # (faulty results for R < 3.3.3 may be due to unstated dependencies in pbkrtest) 14 | has_pbkrtest <- requireNamespace("pbkrtest", quietly = TRUE) && getRversion() >= "3.3.3" 15 | 16 | data("sleepstudy", package="lme4") 17 | 18 | #################################### 19 | ## Tests of contest1D 20 | #################################### 21 | 22 | fm <- lmer(Reaction ~ Days + I(Days^2) + (1|Subject) + (0+Days|Subject), 23 | sleepstudy) 24 | # Basic tests: 25 | L <- c(0, 1, 0) 26 | contest1D(fm, L) 27 | contest1D(fm, L, confint = TRUE) 28 | contest1D(fm, L, confint = TRUE, level=0.99) 29 | if(has_pbkrtest) 30 | contest1D(fm, L, ddf="Kenward-Roger") 31 | 32 | # Test too long L 33 | assertError(contest1D(fm, c(0, 1, 1, 1))) 34 | 35 | # Test too short L 36 | assertError(contest1D(fm, c(0, 1))) 37 | 38 | # Test matrix L 39 | contest1D(fm, matrix(L, nrow=1)) 40 | contest1D(fm, matrix(L, ncol=1)) 41 | assertError(contest1D(fm, matrix(c(0, 1), ncol=1))) 42 | assertError(contest1D(fm, matrix(c(0, 1, 0, 0), nrow=1))) 43 | L <- matrix(numeric(0L), ncol=3) 44 | assertError(contest1D(fm, L)) # "empty" matrix 45 | assertError(contest1D(fm, matrix(1, ncol=3, nrow=2))) 46 | 47 | # Test list L 48 | assertError(contest1D(fm, list(c(0, 1, 0)))) 49 | 50 | # Test equivalence to coef(summary(fm)): 51 | Lmat <- diag(length(fixef(fm))) 52 | (coef_mat <- lmerTest:::rbindall(lapply(1:ncol(Lmat), function(i) 53 | contest1D(fm, Lmat[i, ])))) 54 | (coef_mat_lme4 <- coef(summary(fm, ddf="lme4"))) 55 | rownames(coef_mat) <- rownames(coef_mat_lme4) 56 | stopifnot(isTRUE( 57 | all.equal(as.data.frame(coef_mat_lme4), 58 | coef_mat[, c("Estimate", "Std. Error", "t value")], tolerance=TOL) 59 | )) 60 | 61 | if(has_pbkrtest) { 62 | (coef_mat_KR <- lmerTest:::rbindall(lapply(1:ncol(Lmat), function(i) 63 | contest1D(fm, Lmat[i, ], ddf="Kenward-Roger")))) 64 | rownames(coef_mat_KR) <- rownames(coef_mat_lme4) 65 | stopifnot(isTRUE( 66 | all.equal(as.data.frame(coef_mat_lme4), 67 | coef_mat_KR[, c("Estimate", "Std. Error", "t value")], tolerance=TOL) 68 | )) 69 | } 70 | # Test of 0-length beta 71 | fm1 <- lmer(Reaction ~ 0 + (1|Subject) + (0+Days|Subject), 72 | sleepstudy) 73 | stopifnot(length(fixef(fm1)) == 0L) 74 | if(has_pbkrtest) { 75 | (ans <- contest1D(fm1, numeric(0L), ddf="Kenward-Roger")) 76 | stopifnot(nrow(ans) == 0L) 77 | } 78 | 79 | ## Test rhs argument: 80 | fm <- lmer(Reaction ~ Days + (Days|Subject), sleepstudy) 81 | contest1D(fm, L=cbind(0, 1)) 82 | contest1D(fm, L=cbind(0, 1), rhs=10) 83 | if(has_pbkrtest) { 84 | contest1D(fm, L=cbind(0, 1), ddf="Kenward-Roger") 85 | contest1D(fm, L=cbind(0, 1), ddf="Kenward-Roger", rhs=10) 86 | } 87 | 88 | contest1D(fm, L=c(0, 1), rhs = 10.467) 89 | 90 | (ct1 <- contest1D(fm, L=cbind(c(0, 1)), rhs = 10)) 91 | (ct2 <- contestMD(fm, L=rbind(c(0, 1)), rhs = 10)) 92 | stopifnot( 93 | isTRUE(all.equal(ct1[, "t value"]^2, ct2[, "F value"], tolerance=1e-6)) 94 | ) 95 | 96 | ## Test 'lmerMod' method: 97 | fm <- lme4::lmer(Reaction ~ Days + I(Days^2) + (1|Subject) + (0+Days|Subject), 98 | sleepstudy) 99 | # Basic tests: 100 | L <- c(0, 1, 0) 101 | contest1D(fm, L) 102 | contest1D(fm, L, confint = TRUE) 103 | contest1D(fm, L, confint = TRUE, level=0.99) 104 | if(has_pbkrtest) 105 | contest1D(fm, L, ddf="Kenward-Roger") 106 | 107 | -------------------------------------------------------------------------------- /tests/test_contestMD.R: -------------------------------------------------------------------------------- 1 | # test_contestMD.R 2 | library(lmerTest) 3 | 4 | # WRE says "using if(requireNamespace("pkgname")) is preferred, if possible." 5 | # even in tests: 6 | assertError <- function(expr, ...) 7 | if(requireNamespace("tools")) tools::assertError(expr, ...) else invisible() 8 | assertWarning <- function(expr, ...) 9 | if(requireNamespace("tools")) tools::assertWarning(expr, ...) else invisible() 10 | 11 | # Kenward-Roger only available with pbkrtest and only then validated in R >= 3.3.3 12 | # (faulty results for R < 3.3.3 may be due to unstated dependencies in pbkrtest) 13 | has_pbkrtest <- requireNamespace("pbkrtest", quietly = TRUE) && getRversion() >= "3.3.3" 14 | 15 | data("sleepstudy", package="lme4") 16 | 17 | #################################### 18 | ## Tests of contestMD 19 | #################################### 20 | 21 | fm <- lmer(Reaction ~ Days + I(Days^2) + (1|Subject) + (0+Days|Subject), 22 | sleepstudy) 23 | # Basic tests: 24 | L <- diag(3L) 25 | contestMD(fm, L) 26 | 27 | # Tests of ddf arg: 28 | contestMD(fm, L, ddf="Sat") 29 | if(has_pbkrtest) 30 | contestMD(fm, L, ddf="Kenward-Roger") 31 | assertError(contestMD(fm, L, ddf="sat")) # Invalid ddf arg. 32 | 33 | # Tests of simple 2-df test: 34 | (ans <- contestMD(fm, L[2:3, ], ddf="Sat")) 35 | stopifnot(nrow(ans) == 1L, 36 | ans$NumDF == 2L) 37 | if(has_pbkrtest) { 38 | (ans <- contestMD(fm, L[2:3, ], ddf="Kenward-Roger")) 39 | stopifnot(nrow(ans) == 1L, 40 | ans$NumDF == 2L) 41 | } 42 | 43 | # Tests of simple 1-df test: 44 | (ans <- contestMD(fm, L[3, , drop=FALSE], ddf="Sat")) 45 | stopifnot(nrow(ans) == 1L, 46 | ans$NumDF == 1L) 47 | if(has_pbkrtest) { 48 | (ans <- contestMD(fm, L[3, , drop=FALSE], ddf="Kenward-Roger")) 49 | stopifnot(nrow(ans) == 1L, 50 | ans$NumDF == 1L) 51 | } 52 | 53 | # Test of vector input: 54 | (ans <- contestMD(fm, L[3, ], ddf="Sat")) # OK since length(L[3, ]) == length(fixef(fm)) 55 | stopifnot(nrow(ans) == 1L, 56 | ans$NumDF == 1L) 57 | assertError(contestMD(fm, c(1, 0))) # L is too short 58 | assertError(contestMD(fm, c(1, 0, 1, 1))) # L is too long 59 | 60 | # Test of list input: 61 | assertError(contestMD(fm, list(L[3, , drop=FALSE]), ddf="Sat")) # Need L to be a matrix 62 | 63 | # zero-row L's are allowed (if ncol(L) is correct): 64 | ans1 <- contestMD(fm, L[0, , drop=FALSE], ddf="Sat") 65 | stopifnot(nrow(ans1) == 0L) 66 | if(has_pbkrtest) { 67 | ans2 <- contestMD(fm, L[0, , drop=FALSE], ddf="Kenward-Roger") 68 | stopifnot(nrow(ans2) == 0L) 69 | } 70 | 71 | # Test wrong ncol(L): 72 | assertError(contestMD(fm, L[2:3, 2:3])) # need ncol(L) == length(fixef(fm)) 73 | 74 | # row-rank deficient L are allowed: 75 | L <- rbind(c(1, 0, 1), 76 | c(0, 1, 0), 77 | c(1, -1, 1)) 78 | ans <- contestMD(fm, L) 79 | stopifnot(nrow(L) == 3L, 80 | qr(L)$rank == 2, 81 | ans$NumDF == 2) 82 | if(has_pbkrtest) { 83 | ans_KR <- contestMD(fm, L, ddf="Kenward-Roger") 84 | stopifnot(ans_KR$NumDF == 2) 85 | } 86 | 87 | # Test of 0-length beta 88 | fm1 <- lmer(Reaction ~ 0 + (1|Subject) + (0+Days|Subject), 89 | sleepstudy) 90 | stopifnot(length(fixef(fm1)) == 0L) 91 | L <- numeric(0L) 92 | (ans <- contestMD(fm1, L)) 93 | stopifnot(nrow(ans) == 0L) 94 | L <- matrix(numeric(0L), ncol=0L) 95 | (ans <- contestMD(fm1, L)) 96 | stopifnot(nrow(ans) == 0L) 97 | 98 | 99 | ## rhs argument: 100 | data("cake", package="lme4") 101 | model <- lmer(angle ~ recipe * temp + (1|recipe:replicate), cake) 102 | (L <- diag(length(fixef(model)))[2:3, ]) 103 | (an <- anova(model, type="marginal")) 104 | 105 | ct <- contestMD(model, L, rhs = 0) 106 | ct2 <- contestMD(model, L, rhs = c(2, 2)) 107 | stopifnot( 108 | isTRUE(all.equal(ct[1, ], an[1, ], check.attributes=FALSE, tolerance=1e-6)), 109 | ct[, "F value"] < ct2[, "F value"] 110 | ) 111 | 112 | L2 <- rbind(L, L[1, ] + L[2, ]) # rank deficient! 113 | contestMD(model, L2, rhs = c(0, 0, 0)) # no warning 114 | assertWarning(contestMD(model, L2, rhs = c(2, 2, 2))) # warning since L2 is rank def. 115 | if(has_pbkrtest) 116 | assertWarning(contestMD(model, L2, rhs = c(2, 2, 2), ddf="Kenward-Roger")) 117 | 118 | fm <- lmer(Reaction ~ Days + (Days|Subject), sleepstudy) 119 | contestMD(fm, L=cbind(0, 1)) 120 | contestMD(fm, L=cbind(0, 1), rhs=10) 121 | if(has_pbkrtest) { 122 | contestMD(fm, L=cbind(0, 1), ddf="Kenward-Roger") 123 | contestMD(fm, L=cbind(0, 1), ddf="Kenward-Roger", rhs=10) 124 | } 125 | 126 | 127 | ## Test 'lmerMod' method: 128 | fm <- lme4::lmer(Reaction ~ Days + (Days|Subject), sleepstudy) 129 | contestMD(fm, L=cbind(0, 1)) 130 | contestMD(fm, L=cbind(0, 1), rhs=10) 131 | if(has_pbkrtest) { 132 | contestMD(fm, L=cbind(0, 1), ddf="Kenward-Roger") 133 | contestMD(fm, L=cbind(0, 1), ddf="Kenward-Roger", rhs=10) 134 | } 135 | -------------------------------------------------------------------------------- /tests/test_contrast_utils.R: -------------------------------------------------------------------------------- 1 | # test_contrast_utils.R 2 | 3 | library(lmerTest) 4 | 5 | ########## 6 | # Test that a message is printed if some cells have zero data: 7 | # Missing a single cell: 8 | data("cake", package="lme4") 9 | cake4 <- cake 10 | cake4$temperature <- factor(cake4$temperature, ordered=FALSE) 11 | cake4 <- droplevels(subset(cake4, !(recipe == "A" & temperature == "175") )) 12 | with(cake4, table(recipe, temperature)) 13 | 14 | fm1 <- lmer(angle ~ recipe * temperature + (1|recipe:replicate), cake4) 15 | an <- anova(fm1) 16 | txt <- capture.output(an <- anova(fm1), type = "message") 17 | stopifnot(length(grep("Missing cells for:", txt)) > 0, 18 | length(grep("Interpret type III hypotheses with care.", txt)) > 0) 19 | 20 | ########## 21 | # Test that a message is printed if some cells have zero data: 22 | # Missing diagonal: 23 | cake4 <- cake 24 | cake4$temperature <- factor(cake4$temperature, ordered=FALSE) 25 | cake4 <- droplevels(subset(cake4, temperature %in% levels(cake4$temperature)[1:3])) 26 | cake4 <- droplevels(subset(cake4, !((recipe == "A" & temperature == "175") | 27 | (recipe == "B" & temperature == "185") | 28 | (recipe == "C" & temperature == "195") ))) 29 | cake4$temp0 <- cake4$temp - mean(cake4$temp) 30 | with(cake4, table(recipe, temperature)) 31 | 32 | fm1 <- lmer(angle ~ recipe * temperature + (1|recipe:replicate), cake4) 33 | an <- anova(fm1) 34 | txt <- capture.output(an <- anova(fm1), type = "message") 35 | stopifnot(length(grep("Missing cells for:", txt)) > 0, 36 | length(grep("Interpret type III hypotheses with care.", txt)) > 0) 37 | 38 | ########## 39 | # Test that a message is NOT printed with centered covariates: 40 | fm1 <- lmer(angle ~ recipe * temp0 + (1|recipe:replicate), cake4) 41 | an <- anova(fm1) 42 | txt <- capture.output(an <- anova(fm1), type = "message") 43 | stopifnot(length(grep("Missing cells for:", txt)) == 0, 44 | length(grep("Interpret type III hypotheses with care.", txt)) == 0) 45 | # Note: in many cases a message would not be printed anyway because the 46 | # columns sums in the rdX design matrix would not be exactly zero but just a 47 | # small number very close to zero. 48 | 49 | 50 | 51 | -------------------------------------------------------------------------------- /tests/test_drop1.R: -------------------------------------------------------------------------------- 1 | # test_drop1.R 2 | 3 | library(lmerTest) 4 | 5 | # WRE says "using if(requireNamespace("pkgname")) is preferred, if possible." 6 | # even in tests: 7 | assertError <- function(expr, ...) 8 | if(requireNamespace("tools")) tools::assertError(expr, ...) else invisible() 9 | assertWarning <- function(expr, ...) 10 | if(requireNamespace("tools")) tools::assertWarning(expr, ...) else invisible() 11 | 12 | TOL <- 1e-4 13 | # Kenward-Roger only available with pbkrtest and only then validated in R >= 3.3.3 14 | # (faulty results for R < 3.3.3 may be due to unstated dependencies in pbkrtest) 15 | has_pbkrtest <- requireNamespace("pbkrtest", quietly = TRUE) && getRversion() >= "3.3.3" 16 | 17 | data("sleepstudy", package="lme4") 18 | 19 | ######### Basic usage 20 | 21 | data("cake", package="lme4") 22 | cake2 <- cake 23 | cake2$temperature <- factor(cake2$temperature, ordered = FALSE) 24 | fm <- lmer(angle ~ recipe + temperature + (1|recipe:replicate), cake2) 25 | (an1 <- drop1(fm)) 26 | (an2 <- drop1(fm, force_get_contrasts = TRUE)) 27 | drop1(fm, ddf="lme4", test="Chi") 28 | if(has_pbkrtest) 29 | drop1(fm, ddf="Kenward-Roger") 30 | 31 | tests1 <- show_tests(an1) 32 | tests2 <- show_tests(an2) 33 | 34 | stopifnot( 35 | # Tests are the same: 36 | isTRUE(all.equal(an1, an2, check.attributes = FALSE, tolerance=TOL)), 37 | # But contrast matrices are not: 38 | all(!mapply(function(x, y) isTRUE(all.equal(x, y)), tests1, tests2)) 39 | ) 40 | 41 | fm <- lmer(angle ~ recipe * temperature + (1|recipe:replicate), cake2) 42 | drop1(fm) 43 | drop1(fm, ddf="lme4") 44 | if(has_pbkrtest) 45 | drop1(fm, ddf="Kenward-Roger") 46 | 47 | # Incorrect arguments: 48 | assertError(drop1(fm, scope="recipe")) # Correct Error 49 | assertError(drop1(fm, scope=3)) # Correct Error 50 | assertError(drop1(fm, scope=list("recipe"))) # Correct Error 51 | 52 | # Polynomial terms: 53 | 54 | fm <- lmer(Reaction ~ 0 + (Days|Subject), sleepstudy) 55 | (an0 <- drop1(fm)) # No fixef! 56 | fm <- lmer(Reaction ~ Days + (Days|Subject), sleepstudy) 57 | (an1 <- drop1(fm)) 58 | fm <- lmer(Reaction ~ Days + I(Days^2) + (Days|Subject), sleepstudy) 59 | (an2 <- (drop1(fm))) 60 | fm <- lmer(Reaction ~ poly(Days, 2) + (Days|Subject), sleepstudy) 61 | (an3 <- drop1(fm)) 62 | stopifnot( 63 | nrow(an0) == 0L, 64 | nrow(an1) == 1L, 65 | nrow(an2) == 2L, 66 | nrow(an3) == 1L 67 | ) 68 | 69 | # Consider a rank-deficient design matrix: 70 | fm <- lmer(angle ~ recipe + temp + temperature + (1|recipe:replicate), cake) 71 | # Here temp accounts for the linear effect of temperature, and 72 | # temperature is an (ordered) factor that accounts for the remaining 73 | # variation between temperatures (4 df). 74 | (an4 <- drop1(fm)) 75 | # While temperature is in the model, we cannot test the effect of dropping 76 | # temp. After removing temperature we can test the effect of dropping temp: 77 | (an5 <- drop1(update(fm, ~.-temperature))) 78 | 79 | stopifnot( 80 | nrow(an4) == 3, 81 | rownames(an4)[2] == "temp", 82 | all(is.na(an4[2, ])), 83 | all(!is.na(an4[-2, ])), 84 | all(rownames(an5) == c("recipe", "temp")) 85 | ) 86 | 87 | 88 | 89 | -------------------------------------------------------------------------------- /tests/test_legacy.R: -------------------------------------------------------------------------------- 1 | # test_legacy.R 2 | library(lmerTest) 3 | TOL <- 1e-4 4 | ##################################################################### 5 | 6 | # Read in data set 7 | load(system.file("testdata", "legacy_fits.RData", package="lmerTest")) 8 | # Generated with the following code using lmerTest version 2.0-37.9002 9 | # 10 | # library("lmerTest") 11 | # packageVersion("lmerTest") 12 | # fm1 <- lmer(Reaction ~ Days + (Days|Subject), sleepstudy) 13 | # (an1 <- anova(fm1)) 14 | # (sfm1 <- summary(fm1)) 15 | # 16 | # fm2 <- lmer(Informed.liking ~ Product + Information + Gender + 17 | # (1|Product:Consumer) , data=ham) 18 | # (an2 <- anova(fm2)) 19 | # (sfm2 <- summary(fm2)) 20 | # 21 | # save(fm1, an1, sfm1, fm2, an2, sfm2, 22 | # file="~/GitHub/lmerTestR/package/inst/testdata/legacy_fits.RData") 23 | 24 | 25 | ####################################### 26 | ### Check that arguments for merModLmerTest and lmerModLmerTest methods match up: 27 | 28 | stopifnot( 29 | isTRUE(all.equal(formals(lmerTest:::anova.merModLmerTest), 30 | formals(lmerTest:::anova.lmerModLmerTest))), 31 | isTRUE(all.equal(formals(lmerTest:::summary.merModLmerTest), 32 | formals(lmerTest:::summary.lmerModLmerTest))), 33 | isTRUE(all.equal(formals(lmerTest:::drop1.merModLmerTest), 34 | formals(lmerTest:::drop1.lmerModLmerTest))), 35 | isTRUE(all.equal(formals(lmerTest:::step.merModLmerTest), 36 | formals(lmerTest:::step.lmerModLmerTest))), 37 | isTRUE(all.equal(formals(lmerTest:::ls_means.merModLmerTest), 38 | formals(lmerTest:::ls_means.lmerModLmerTest))), 39 | isTRUE(all.equal(formals(lmerTest:::difflsmeans.merModLmerTest), 40 | formals(lmerTest:::difflsmeans.lmerModLmerTest)))) 41 | 42 | 43 | ####################################### 44 | ## Tests for fm1: 45 | 46 | an1new <- anova(fm1) 47 | sfm1new <- summary(fm1) 48 | 49 | stopifnot( 50 | isTRUE(all.equal(an1new, an1, check.attributes=FALSE, tol=TOL)), 51 | isTRUE(all.equal(coef(sfm1new), coef(sfm1), tol=TOL)) 52 | ) 53 | 54 | contest(fm1, c(0, 1)) 55 | contest(fm1, c(0, 1), joint=FALSE) 56 | drop1(fm1) 57 | ranova(fm1) 58 | step(fm1) 59 | 60 | fm1new <- lmer(Reaction ~ Days + (Days|Subject), sleepstudy, 61 | control=lmerControl(optimizer="bobyqa")) 62 | stopifnot( 63 | isTRUE(all.equal(drop1(fm1), drop1(fm1new), tol=TOL)), 64 | isTRUE(all.equal(ranova(fm1), ranova(fm1new), tol=TOL)), 65 | isTRUE(all.equal(contest(fm1, c(0, 1)), contest(fm1new, c(0, 1)), tol=TOL)), 66 | isTRUE(all.equal(contest(fm1, c(0, 1), joint=FALSE), 67 | contest(fm1new, c(0, 1), joint=FALSE), tol=TOL)) 68 | ) 69 | 70 | # Test that lme4 methods work: 71 | coef(fm1) 72 | fixef(fm1) 73 | resid(fm1) 74 | 75 | ####################################### 76 | ## Tests for fm2: 77 | an2new <- anova(fm2) 78 | sfm2new <- summary(fm2) 79 | 80 | stopifnot( 81 | isTRUE(all.equal(an2new, an2, check.attributes=FALSE, tol=TOL)), 82 | isTRUE(all.equal(coef(sfm2new), coef(sfm2), tol=TOL)) 83 | ) 84 | 85 | drop1(fm2) 86 | ranova(fm2) 87 | ls_means(fm2) 88 | difflsmeans(fm2) 89 | nbeta <- length(fixef(fm2)) 90 | L <- diag(nbeta) 91 | L[1:4, ] <- 0 92 | contest(fm2, L) 93 | contest(fm2, diag(nbeta), joint=FALSE) 94 | step(fm2) 95 | 96 | fm2new <- lmer(Informed.liking ~ Product + Information + Gender + 97 | (1|Product:Consumer), data=ham) 98 | stopifnot( 99 | isTRUE(all.equal(drop1(fm2), drop1(fm2new), tol=TOL)), 100 | isTRUE(all.equal(ranova(fm2), ranova(fm2new), tol=TOL)), 101 | isTRUE(all.equal(ls_means(fm2), ls_means(fm2new), tol=TOL)), 102 | isTRUE(all.equal(difflsmeans(fm2), difflsmeans(fm2new), tol=TOL)) 103 | ) 104 | 105 | # Test that lme4 methods work: 106 | coef(fm2) 107 | fixef(fm2) 108 | resid(fm2) 109 | 110 | -------------------------------------------------------------------------------- /tests/test_lmer.R: -------------------------------------------------------------------------------- 1 | # test_lmer.R 2 | 3 | stopifnot(!"lmerTest" %in% .packages()) # ensure that lmerTest is NOT attached 4 | data("sleepstudy", package="lme4") 5 | f <- function(form, data) lmerTest::lmer(form, data=data) 6 | form <- "Reaction ~ Days + (Days|Subject)" 7 | fm <- f(form, data=sleepstudy) 8 | anova(fm) 9 | summary(fm) 10 | 11 | # cf. GitHub issue #2: 12 | test <- function() { 13 | tmp <- sleepstudy 14 | m <- lmerTest::lmer(Reaction ~ Days + (Days | Subject), data = tmp) 15 | summary(m) 16 | } 17 | test() 18 | test <- function() { 19 | tmp <- sleepstudy 20 | m <- lme4::lmer(Reaction ~ Days + (Days | Subject), data = tmp) 21 | if(requireNamespace("lmerTest", quietly = TRUE)) { 22 | summary(lmerTest::as_lmerModLmerTest(m)) 23 | } 24 | } 25 | test() 26 | 27 | library(lmerTest) 28 | 29 | # WRE says "using if(requireNamespace("pkgname")) is preferred, if possible." 30 | # even in tests: 31 | assertError <- function(expr, ...) 32 | if(requireNamespace("tools")) tools::assertError(expr, ...) else invisible() 33 | assertWarning <- function(expr, ...) 34 | if(requireNamespace("tools")) tools::assertWarning(expr, ...) else invisible() 35 | 36 | TOL <- 1e-4 37 | 38 | ##################################################################### 39 | # Check that lme4::lmer and lmerTest::lmer have the same arguments 40 | 41 | lmer_args <- formals(lme4::lmer) 42 | names(lmer_args) 43 | lmerTest_args <- formals(lmerTest::lmer) 44 | seq_args <- seq_along(lmerTest_args) 45 | if(packageVersion("lme4") > '1.1.21') { 46 | stopifnot( 47 | all.equal(names(lmer_args), names(lmerTest_args)), 48 | all.equal(lmer_args, lmerTest_args) 49 | ) 50 | } else { # Older versions of 'lme4' has a "..." argument: 51 | stopifnot( 52 | all.equal(names(lmer_args)[seq_args], names(lmerTest_args[seq_args])), 53 | all.equal(lmer_args[seq_args], lmerTest_args[seq_args]) 54 | ) 55 | } 56 | 57 | ##################################################################### 58 | # Test evaluation of update inside a function: 59 | myupdate <- function(m, ...) { 60 | update(m, ...) 61 | } 62 | 63 | data("sleepstudy", package="lme4") 64 | fm1 <- lmer(Reaction ~ Days + (Days|Subject), sleepstudy) 65 | tmp <- sleepstudy 66 | rm(sleepstudy) 67 | fmA <- update(fm1, data = tmp) # works 68 | fmB <- myupdate(fm1, data = tmp) # also works 69 | # Same except for 'call': 70 | fmB@call <- fmA@call 71 | stopifnot(isTRUE(all.equal(fmA, fmB, tolerance=TOL))) 72 | # Based on bug-report by Henrik Singmann, github issue #3 73 | 74 | ##################################################################### 75 | # Test update when formula is a character vector: 76 | 77 | form <- "Informed.liking ~ Product+Information+ 78 | (1|Consumer) + (1|Product:Consumer) + (1|Information:Consumer)" 79 | m <- lmer(form, data=ham) 80 | class(m) 81 | class(update(m, ~.- Product)) 82 | stopifnot(inherits(update(m, ~.- Product), "lmerModLmerTest")) 83 | 84 | # In version < 3.0-1.9002 class(update(m, ~.- Product)) was "lmerMod" 85 | ##################################################################### 86 | # Test error message from as_lmerModLmerTest: 87 | data("sleepstudy", package="lme4") 88 | myfit <- function(formula, data) { 89 | lme4::lmer(formula = formula, data = data) 90 | } 91 | fm2 <- myfit(Reaction ~ Days + (Days|Subject), sleepstudy) 92 | m <- assertError(as_lmerModLmerTest(fm2)) 93 | stopifnot( 94 | grepl("Unable to extract deviance function from model fit", m[[1]], fixed=TRUE) 95 | ) 96 | 97 | ##################################################################### 98 | # Check that devFunOnly argument works: 99 | data("sleepstudy", package="lme4") 100 | fun <- lmer(Reaction ~ Days + (Days|Subject), sleepstudy, devFunOnly = TRUE) 101 | stopifnot(is.function(fun) && names(formals(fun)[1]) == "theta") 102 | fm1 <- lmer(Reaction ~ Days + (Days|Subject), sleepstudy) 103 | fun <- update(fm1, devFunOnly=TRUE) 104 | stopifnot(is.function(fun) && names(formals(fun)[1]) == "theta") 105 | # devFunOnly = FALSE: 106 | notfun <- lmer(Reaction ~ Days + (Days|Subject), sleepstudy, devFunOnly = FALSE) 107 | stopifnot(inherits(notfun, "lmerModLmerTest")) 108 | # Partial matching: 109 | notfun <- lmer(Reaction ~ Days + (Days|Subject), sleepstudy, devFun = FALSE) 110 | stopifnot(inherits(notfun, "lmerModLmerTest")) 111 | 112 | ##################################################################### 113 | # Use of as_lmerModLmerTest 114 | data("sleepstudy", package="lme4") 115 | m <- lme4::lmer(Reaction ~ Days + (Days | Subject), sleepstudy) 116 | bm <- lmerTest:::as_lmerModLmerTest(m) 117 | stopifnot( 118 | inherits(bm, "lmerModLmerTest"), 119 | !inherits(m, "lmerModLmerTest"), 120 | inherits(bm, "lmerMod"), 121 | all(c("vcov_varpar", "Jac_list", "vcov_beta", "sigma") %in% slotNames(bm)) 122 | ) 123 | 124 | ##################################################################### 125 | # Update method 126 | 127 | m <- lmer(Reaction ~ Days + (Days | Subject), sleepstudy) 128 | m1 <- update(m, ~.-Days) 129 | m2 <- lmer(Reaction ~ (Days | Subject), sleepstudy) 130 | 131 | stopifnot( 132 | inherits(m, "lmerModLmerTest"), 133 | inherits(m1, "lmerModLmerTest"), 134 | inherits(m2, "lmerModLmerTest"), 135 | all.equal(m1, m2, tolerance=1e-6) 136 | ) 137 | 138 | -------------------------------------------------------------------------------- /tests/test_lmerTest_paper.R: -------------------------------------------------------------------------------- 1 | # test_lmerTest_paper.R 2 | 3 | library(lmerTest) 4 | 5 | # Kenward-Roger only available with pbkrtest and only then validated in R >= 3.3.3 6 | # (faulty results for R < 3.3.3 may be due to unstated dependencies in pbkrtest) 7 | has_pbkrtest <- requireNamespace("pbkrtest", quietly = TRUE) && getRversion() >= "3.3.3" 8 | 9 | # Read in data set 10 | load(system.file("testdata","test_paper_objects.RData", package="lmerTest")) 11 | 12 | # Evaluate code from paper: 13 | ## Section 8.2: 14 | tv <- lmer(Sharpnessofmovement ~ TVset * Picture + (1 | Assessor) + 15 | (1 | Assessor:TVset) + (1 | Assessor:Picture), data = TVbo, 16 | control=lmerControl(optimizer="bobyqa")) 17 | 18 | (an8.2 <- anova(tv)) 19 | 20 | if(has_pbkrtest) 21 | (ankr8.2 <- anova(tv, type=2, ddf="Kenward-Roger")) 22 | 23 | ## Section 8.3: 24 | m.carrots <- lmer(Preference ~ sens1 + sens2 + (1 + sens1 + sens2 | Consumer) + 25 | (1 | Product), data=carrots, 26 | control=lmerControl(optimizer="bobyqa")) 27 | (sum8.3 <- coef(summary(m.carrots))) 28 | 29 | ## Section 8.4: 30 | tv <- lmer(Sharpnessofmovement ~ TVset * Picture + 31 | (1 | Assessor:TVset) + (1 | Assessor:Picture) + 32 | (1 | Assessor:Picture:TVset) + (1 | Repeat) + (1 | Repeat:Picture) + 33 | (1 | Repeat:TVset) + (1 | Repeat:TVset:Picture) + (1 | Assessor), 34 | data = TVbo, 35 | control=lmerControl(optimizer="bobyqa")) 36 | st <- step(tv) 37 | (elim_tab_random8.4 <- st$random) 38 | (elim_tab_fixed8.4 <- st$fixed) 39 | (an8.4 <- anova(get_model(st))) 40 | 41 | ## Section 8.5: 42 | # L <- matrix(0, ncol = 12, nrow = 6) 43 | # L[1, 7] <- L[2, 8] <- L[3, 9] <- L[4, 10] <- L[5, 11] <- L[6, 12] <- 1 44 | L <- cbind(array(0, dim=c(6, 6)), diag(6)) 45 | (con1_8.5 <- calcSatterth(tv, L)) 46 | (con2_8.5 <- contest(tv, L)) 47 | 48 | ## Section C: 49 | # m.carrots <- lmer(Preference ~ sens1 + sens2 + (1 + sens1 + sens2 | Consumer) + 50 | # (1 | product), data = carrots) 51 | # step(m.carrots, reduce.fixed = FALSE) 52 | (ran_C <- ranova(m.carrots)) 53 | 54 | # Compare to validated outputs: 55 | TOL <- 1e-4 56 | stopifnot( 57 | isTRUE(all.equal(an8.2_save, an8.2, check.attributes = FALSE, tolerance=TOL)), 58 | isTRUE(all.equal(sum8.3_save, sum8.3, check.attributes = FALSE, tolerance=TOL)), 59 | isTRUE(all.equal(elim_tab_random8.4_save, elim_tab_random8.4, 60 | check.attributes = FALSE, tolerance=TOL)), 61 | isTRUE(all.equal(elim_tab_fixed8.4_save, elim_tab_fixed8.4, 62 | check.attributes = FALSE, tolerance=TOL)), 63 | isTRUE(all.equal(an8.4_save, an8.4, check.attributes = FALSE, tolerance=TOL)), 64 | isTRUE(all.equal(con1_8.5_save, con1_8.5, check.attributes = FALSE, tolerance=TOL)), 65 | isTRUE(all.equal(con2_8.5_save, con2_8.5, check.attributes = FALSE, tolerance=TOL)) 66 | ) 67 | if(has_pbkrtest) { 68 | stopifnot( 69 | isTRUE(all.equal(ankr8.2_save, ankr8.2, check.attributes = FALSE, tolerance=TOL)) 70 | ) 71 | } 72 | 73 | -------------------------------------------------------------------------------- /tests/test_ls_means.R: -------------------------------------------------------------------------------- 1 | # test_lsmeans.R 2 | 3 | library(lmerTest) 4 | 5 | TOL <- 1e-4 6 | # Kenward-Roger only available with pbkrtest and only then validated in R >= 3.3.3 7 | # (faulty results for R < 3.3.3 may be due to unstated dependencies in pbkrtest) 8 | has_pbkrtest <- requireNamespace("pbkrtest", quietly = TRUE) && getRversion() >= "3.3.3" 9 | 10 | ########### Basic model structures: 11 | 12 | # Factor * covariate: 13 | data("cake", package="lme4") 14 | model <- lmer(angle ~ recipe * temp + (1|recipe:replicate), cake) 15 | (lsm <- ls_means(model)) 16 | stopifnot( 17 | nrow(lsm) == 3L, 18 | ncol(lsm) == 7L, 19 | # Balanced, so LS-means equal raw means: 20 | isTRUE(all.equal(c(with(cake, tapply(angle, recipe, mean))), lsm[, "Estimate"], 21 | check.attributes=FALSE, tolerance=TOL)) 22 | ) 23 | 24 | # Pairwise differences of LS-means: 25 | plsm <- ls_means(model, pairwise = TRUE) 26 | plsm2 <- difflsmeans(model) 27 | C <- as.matrix(lmerTest:::get_pairs(rownames(lsm))) 28 | stopifnot( 29 | isTRUE(all.equal(plsm, plsm2, tolerance=TOL)), 30 | isTRUE(all.equal(plsm[, "Estimate"], c(lsm[, "Estimate"] %*% C), 31 | check.attributes=FALSE, tolerance=TOL)) 32 | ) 33 | 34 | # Contrasts vectors: 35 | show_tests(lsm) 36 | show_tests(plsm) 37 | 38 | # Factor * Ordered: 39 | model <- lmer(angle ~ recipe * temperature + (1|recipe:replicate), cake) 40 | (lsm2 <- ls_means(model)) 41 | stopifnot( 42 | nrow(lsm2) == 3 + 6 + 3*6, 43 | ncol(lsm) == 7L, 44 | # Balanced, so LS-means equal raw means: 45 | isTRUE(all.equal(lsm[1:3, ], lsm2[1:3, ], 46 | check.attributes=FALSE, tolerance=TOL)) 47 | ) 48 | 49 | 50 | # Factor * Factor: 51 | cake2 <- cake 52 | cake2$temperature <- factor(cake2$temperature, ordered = FALSE) 53 | model <- lmer(angle ~ recipe * temperature + (1|recipe:replicate), cake2) 54 | (lsm3 <- ls_means(model)) 55 | stopifnot( 56 | isTRUE(all.equal(lsm2, lsm3, check.attributes=FALSE, tolerance=TOL)) 57 | ) 58 | 59 | # Covariate (only): 60 | data("sleepstudy", package="lme4") 61 | m <- lmer(Reaction ~ Days + (Days | Subject), sleepstudy) 62 | (lsm <- ls_means(m)) 63 | stopifnot( 64 | nrow(lsm) == 0L, 65 | ncol(lsm) == 7L 66 | ) 67 | 68 | # No fixef: 69 | m <- lmer(Reaction ~ 0 + (Days | Subject), sleepstudy) 70 | (lsm <- ls_means(m)) 71 | stopifnot( 72 | nrow(lsm) == 0L, 73 | ncol(lsm) == 7L 74 | ) 75 | 76 | ########### Arguments and options: 77 | 78 | # which 79 | model <- lmer(angle ~ recipe * temperature + (1|recipe:replicate), cake2) 80 | (lsm4 <- ls_means(model, which = "recipe")) 81 | stopifnot( 82 | nrow(lsm4) == 3L, 83 | ncol(lsm4) == 7L, 84 | isTRUE(all.equal(lsm3[1:3, ], lsm4, check.attributes=FALSE, tolerance=TOL)) 85 | ) 86 | 87 | # KR: 88 | if(has_pbkrtest) 89 | (lsm5 <- ls_means(model, which = "recipe", ddf = "Kenward-Roger")) 90 | 91 | # level: 92 | (lsm6 <- ls_means(model, which = "recipe", level=0.99)) 93 | 94 | stopifnot( 95 | all(lsm6[, "lower"] < lsm4[, "lower"]), 96 | all(lsm6[, "upper"] > lsm4[, "upper"]) 97 | ) 98 | 99 | 100 | 101 | ########### Missing cels -> unestimable contrasts: 102 | 103 | # Missing cell: 104 | cake3 <- cake 105 | cake3$temperature <- factor(cake3$temperature, ordered=FALSE) 106 | cake3 <- droplevels(subset(cake3, temperature %in% levels(cake3$temperature)[1:3])) 107 | cake3 <- droplevels(subset(cake3, !(recipe == "C" & temperature == "195") )) 108 | str(cake3) 109 | with(cake3, table(recipe, temperature)) 110 | model <- lmer(angle ~ recipe * temperature + (1|recipe:replicate), cake3) 111 | (lsm7 <- ls_means(model)) 112 | 113 | # Using show_tests with options: 114 | show_tests(lsm7, fractions = TRUE) 115 | show_tests(lsm7, fractions = TRUE, names = FALSE) 116 | 117 | # Missing diagonal: 118 | cake4 <- cake 119 | cake4$temperature <- factor(cake4$temperature, ordered=FALSE) 120 | cake4 <- droplevels(subset(cake4, temperature %in% levels(cake4$temperature)[1:3])) 121 | cake4 <- droplevels(subset(cake4, !((recipe == "A" & temperature == "175") | 122 | (recipe == "B" & temperature == "185") | 123 | (recipe == "C" & temperature == "195") ))) 124 | # str(cake4) 125 | with(cake4, table(recipe, temperature)) 126 | model <- lmer(angle ~ recipe * temperature + (1|recipe:replicate), cake4) 127 | ls_means(model) 128 | 129 | 130 | ########### Various contrasts codings: 131 | 132 | model <- lmer(angle ~ recipe * temperature + (1|recipe:replicate), cake3, 133 | contrasts = list(recipe="contr.sum", temperature="contr.helmert")) 134 | (lsm8 <- ls_means(model)) 135 | # show_tests(lsm7) 136 | # show_tests(lsm8) 137 | stopifnot( 138 | isTRUE(all.equal(lsm7, lsm8, check.attributes=FALSE, tolerance=TOL)) 139 | ) 140 | 141 | # ambient contrasts not contr.treatment: 142 | options("contrasts") 143 | options(contrasts = c("contr.sum", "contr.poly")) 144 | model <- lmer(angle ~ recipe * temperature + (1|recipe:replicate), cake3) 145 | (lsm9 <- ls_means(model)) 146 | options(contrasts = c("contr.treatment", "contr.poly")) 147 | options("contrasts") 148 | stopifnot( 149 | isTRUE(all.equal(lsm7, lsm9, check.attributes=FALSE, tolerance=TOL)) 150 | ) 151 | 152 | 153 | -------------------------------------------------------------------------------- /tests/test_summary.R: -------------------------------------------------------------------------------- 1 | # test_summary.R 2 | 3 | # WRE says "using if(requireNamespace("pkgname")) is preferred, if possible." 4 | # even in tests: 5 | assertError <- function(expr, ...) 6 | if(requireNamespace("tools")) tools::assertError(expr, ...) else invisible() 7 | assertWarning <- function(expr, ...) 8 | if(requireNamespace("tools")) tools::assertWarning(expr, ...) else invisible() 9 | 10 | # Kenward-Roger only available with pbkrtest and only then validated in R >= 3.3.3 11 | # (faulty results for R < 3.3.3 may be due to unstated dependencies in pbkrtest) 12 | has_pbkrtest <- requireNamespace("pbkrtest", quietly = TRUE) && getRversion() >= "3.3.3" 13 | 14 | library(lmerTest) 15 | 16 | data("sleepstudy", package="lme4") 17 | data("cake", package="lme4") 18 | 19 | # Fit basic model and compute summary: 20 | fm <- lmer(Reaction ~ Days + (1|Subject) + (0+Days|Subject), sleepstudy) 21 | (sfm <- summary(fm)) 22 | 23 | ## Test class: 24 | stopifnot(all( 25 | class(sfm) == c("summary.lmerModLmerTest", "summary.merMod"), 26 | all(c("df", "Pr(>|t|)") %in% colnames(coef(sfm))) 27 | )) 28 | stopifnot(class(summary(fm, ddf="lme4")) == "summary.merMod") 29 | 30 | ## Test coefficient table names: 31 | mat <- coef(summary(fm)) 32 | stopifnot(all( # colnames 33 | colnames(mat) == c("Estimate", "Std. Error", "df", "t value", "Pr(>|t|)") 34 | )) 35 | stopifnot(all( # rownames 36 | names(fixef(fm)) == rownames(mat) 37 | )) 38 | 39 | ## Test pass of 'correlation' argument to lme4:::summary.merMod: 40 | x <- capture.output(summary(fm)) 41 | x_nocor <- capture.output(summary(fm, correlation=FALSE)) 42 | txt <- "Correlation of Fixed Effects:" 43 | stopifnot( 44 | any(grep(txt, x)), 45 | !any(grepl(txt, x_nocor)) 46 | ) 47 | 48 | # Test warning with unrecognized arguments (caught by lme4:::summary.merMod): 49 | assertWarning(summary(fm, false_arg=FALSE)) 50 | 51 | ## Test pass of extra arguments to lme4:::print.summary.merMod: 52 | x <- capture.output(print(summary(fm), signif.stars=TRUE)) 53 | x_nocor <- capture.output(print(summary(fm), signif.stars=FALSE)) 54 | txt <- "Signif. codes:" 55 | stopifnot( 56 | any(grep(txt, x)), 57 | !any(grepl(txt, x_nocor)) 58 | ) 59 | 60 | ####### ddf argument: 61 | (an1 <- summary(fm)) # Also testing print method. 62 | (an2 <- summary(fm, ddf="Satterthwaite")) 63 | stopifnot(isTRUE( 64 | all.equal(an1, an2) 65 | )) 66 | (an3 <- summary(fm, ddf="Sat")) ## Abbreviated argument 67 | stopifnot(isTRUE( 68 | all.equal(an1, an3) 69 | )) 70 | (summary(fm, ddf="lme4")) 71 | if(has_pbkrtest) { 72 | (summary(fm, ddf="Kenward-Roger")) 73 | assertError(summary(fm, ddf="KR")) ## Error on incorrect arg. 74 | } 75 | 76 | ## lme4 method: 77 | an1 <- summary(fm, ddf="lme4") 78 | an2 <- summary(as(fm, "lmerMod")) 79 | stopifnot(isTRUE( 80 | all.equal(an1, an2) 81 | )) 82 | 83 | 84 | # Test printed output 85 | # - Satterthwaite 86 | x <- capture.output(sfm) # equal to output of 'print(sfm)' 87 | txt <- c("lmerModLmerTest", "t-tests use Satterthwaite's method", 88 | "df", "t value", "Pr(>|t|)") 89 | stopifnot(all( 90 | sapply(txt, function(text) any(grepl(text, x))) 91 | )) 92 | 93 | # Test printed output 94 | # - KR 95 | if(has_pbkrtest) { 96 | (sfm <- summary(fm, ddf="Kenward-Roger")) 97 | x <- capture.output(sfm) 98 | txt <- c("lmerModLmerTest", "t-tests use Kenward-Roger's method", 99 | "df", "t value", "Pr(>|t|)") 100 | stopifnot(all( 101 | sapply(txt, function(text) any(grepl(text, x))) 102 | )) 103 | } 104 | 105 | #################################### 106 | ## Test 'boundary' fixef structures: 107 | #################################### 108 | 109 | # Example with no fixef: 110 | m <- lmer(Reaction ~ -1 + (Days | Subject), sleepstudy) 111 | # m <- lmer(Reaction ~ 0 + (Days | Subject), sleepstudy) # alternative 112 | stopifnot(length(fixef(m)) == 0L) 113 | stopifnot( 114 | nrow(coef(summary(m))) == 0L, 115 | nrow(coef(summary(m, ddf="lme4"))) == 0L 116 | ) 117 | if(has_pbkrtest){ 118 | stopifnot(nrow(coef(summary(m, ddf="Kenward-Roger"))) == 0L) 119 | } 120 | 121 | # Example with intercept only: 122 | m <- lmer(Reaction ~ (Days | Subject), sleepstudy) 123 | # m <- lmer(Reaction ~ 1 + (Days | Subject), sleepstudy) # alternative 124 | stopifnot(length(fixef(m)) == 1L, 125 | names(fixef(m)) == "(Intercept)") 126 | stopifnot( 127 | nrow(coef(summary(m))) == 1L, 128 | nrow(coef(summary(m, ddf="lme4"))) == 1L 129 | ) 130 | if(has_pbkrtest){ 131 | stopifnot(nrow(coef(summary(m, ddf="Kenward-Roger"))) == 1L) 132 | } 133 | 134 | # Example with >1 fixef without intercept: 135 | m <- lmer(Reaction ~ Days - 1 + I(Days^2) + (Days | Subject), sleepstudy) 136 | stopifnot(length(fixef(m)) == 2L, 137 | names(fixef(m)) == c("Days", "I(Days^2)")) 138 | stopifnot( 139 | nrow(coef(summary(m))) == 2L, 140 | nrow(coef(summary(m, ddf="lme4"))) == 2L 141 | ) 142 | if(has_pbkrtest){ 143 | stopifnot(nrow(coef(summary(m, ddf="Kenward-Roger"))) == 2L) 144 | } 145 | 146 | -------------------------------------------------------------------------------- /tests/test_zerovar.R: -------------------------------------------------------------------------------- 1 | # test_zerovar.R 2 | 3 | library(lmerTest) 4 | data("sleepstudy", package="lme4") 5 | 6 | # Baseline fit: 7 | m0 <- lmer(Reaction ~ Days + (Days | Subject), sleepstudy, 8 | control=lmerControl(optimizer="bobyqa")) 9 | ## default optimizer does not converge proporly 10 | m0 11 | (an0 <- anova(m0)) 12 | 13 | # Make a fit with a zero variance estimate: 14 | n <- nrow(sleepstudy) 15 | g <- factor(rep(1:2, c(n - 10, 10))) 16 | m <- lmer(Reaction ~ Days + (Days | Subject) + (1|g), sleepstudy, 17 | control=lmerControl(optimizer="bobyqa")) 18 | m 19 | (an <- anova(m)) 20 | 21 | # check that fit has a zero variance 22 | vc <- as.data.frame(VarCorr(m)) 23 | stopifnot(isTRUE( 24 | all.equal(0, vc[vc$grp == "g", "sdcor"], tolerance=1e-4) 25 | )) 26 | # The hessian/vcov is actually positive definite: 27 | stopifnot(isTRUE( 28 | all(eigen(m@vcov_varpar, only.values = TRUE)$values > 0) 29 | )) 30 | 31 | # Check that ANOVA tables are the same: 32 | stopifnot(isTRUE( 33 | all.equal(an0[, 1:5], an[, 1:5], tolerance=1e-4) 34 | )) 35 | 36 | stopifnot(isTRUE( # Equality of summary tables 37 | all.equal(coef(summary(m0)), coef(summary(m)), tolerance=1e-4) 38 | )) 39 | stopifnot(isTRUE( # Equality of lme4-anova tables 40 | all.equal(anova(m0, ddf="lme4"), anova(m, ddf="lme4"), tolerance=1e-4) 41 | )) 42 | 43 | -------------------------------------------------------------------------------- /tests/zlmerTest_zeroDenom.R: -------------------------------------------------------------------------------- 1 | library(lmerTest) 2 | 3 | # Read in data set 4 | load(system.file("testdata","potdata.RData", package="lmerTest")) 5 | 6 | # Mixed model 7 | lmerout <- lmer(biomass ~ CO2*nutrients + (1|chamber),data=potdata) 8 | summary(lmerout) 9 | 10 | an.sat <- anova(lmerout) 11 | anova(lmerout, ddf="lme4") 12 | TOL <- 1e-5 13 | stopifnot(isTRUE(all.equal( 14 | an.sat[,"DenDF"], c(2, 10, 10), tolerance=TOL 15 | ))) 16 | 17 | stopifnot(isTRUE( 18 | all.equal(an.sat[,"Pr(>F)"], c(0.0224955602, 1e-11, 0.020905569), tolerance=TOL) 19 | )) 20 | 21 | # if(require(pbkrtest)) 22 | # an.kr <- anova(lmerout, ddf="Kenward-Roger") 23 | # 24 | # TOL <- 1e-7 25 | # stopifnot(all.equal(an.kr[,"Pr(>F)"], c(0.0224955602, 1e-11, 0.020905569) , 26 | # tol=TOL), 27 | # all.equal(an.kr[,"DenDF"], 28 | # c(2, 10, 10) , tol=TOL), 29 | # TRUE) 30 | --------------------------------------------------------------------------------