Giter Site home page Giter Site logo

afex's Introduction

afex: Analysis of Factorial EXperiments

CRAN status monthly downloads total downloads Research software impact R-CMD-check

The main functionalities provided by afex are:

  1. Interfaces for estimating standard ANOVAs with any number or combination of within-subjects or between-subjects variables (the ANOVA functions are aov_car(), aov_ez(), and aov_4() which all fit the same model but differ in the way to specify the ANOVA model).
  2. Function mixed() provides an interface for mixed models analysis (estimated via lme4 lmer or glmer) that automatically obtains p-values for fixed effects model terms (i.e., main effects and interactions).
  3. afex_plot() visualizes results from factorial experiments combining estimated marginal means and uncertainties associated with the estimated means in the foreground with a depiction of the raw data in the background.
  4. All afex model objects (i.e., ANOVA and mixed models) can be passed to emmeans for follow-up/post-hoc/planned contrast analysis.

For afex support visit: afex.singmann.science

Installation

  • afex is available from CRAN so the current stable version can be installed directly via: install.packages("afex")

  • To install the latest development version you will need the devtools package: devtools::install_github("singmann/afex@master")

ANOVA functionality

To calculate an ANOVA, afex requires the data to be in the long format (i.e., one row per data point/observation). An ANOVA can then be calculated via one of three functions that only differ in how the model components are specified, but not in the output. Note that in contrast to base lm or aov, afex ANOVA functions always require the specification of a subject identifier column (the id-column), because in case there are multiple observations per participant and cell of the design, these multiple observations are aggregated (i.e., averaged) per default.

  • In aov_ez the columns containing id variable, dependent variable, and factors need to be specified as character vectors.
  • aov_car behaves similar to standard aov and requires the ANOVA to be specified as a formula containing an Error term (at least to identify the id variable).
  • aov_4 allows the ANOVA to be specified via a formula similar to lme4::lmer (with one random effects term).

A further overview is provided by the vignette.

The following code provides a simple example for an ANOVA with both between- and within-subject factors. For this we use the lexical-decision and word naming latencies reported by Freeman, Heathcote, Chalmers, and Hockley (2010), see also ?fhch2010. As is commonly done, we use the natural logarithm of the response times, log_rt, as dependent variable. As independent variable we will consider the between-subjects factor task ("naming" or "lexdec") as well as the within-subjects-factors stimulus ("word" or "nonword") and length (with 3 levels, 3, 4, or 5 letters).

library("afex")
# examples data set with both within- and between-subjects factors (see ?fhch2010)
data("fhch2010", package = "afex")
fhch <- fhch2010[ fhch2010$correct,] # remove errors
str(fhch2010) # structure of the data
#> 'data.frame':    13222 obs. of  10 variables:
#>  $ id       : Factor w/ 45 levels "N1","N12","N13",..: 1 1 1 1 1 1 1 1 1 1 ...
#>  $ task     : Factor w/ 2 levels "naming","lexdec": 1 1 1 1 1 1 1 1 1 1 ...
#>  $ stimulus : Factor w/ 2 levels "word","nonword": 1 1 1 2 2 1 2 2 1 2 ...
#>  $ density  : Factor w/ 2 levels "low","high": 2 1 1 2 1 2 1 1 1 1 ...
#>  $ frequency: Factor w/ 2 levels "low","high": 1 2 2 2 2 2 1 2 1 2 ...
#>  $ length   : Factor w/ 3 levels "4","5","6": 3 3 2 2 1 1 3 2 1 3 ...
#>  $ item     : Factor w/ 600 levels "abide","acts",..: 363 121 202 525 580 135 42 368 227 141 ...
#>  $ rt       : num  1.091 0.876 0.71 1.21 0.843 ...
#>  $ log_rt   : num  0.0871 -0.1324 -0.3425 0.1906 -0.1708 ...
#>  $ correct  : logi  TRUE TRUE TRUE TRUE TRUE TRUE ...
# estimate mixed ANOVA on the full design:
aov_ez("id", "log_rt", fhch, between = "task", within = c("stimulus", "length"))
aov_car(log_rt ~ task * stimulus * length + Error(id/(stimulus * length)), 
        data = fhch)
## equivalent: aov_car(log_rt ~ task + Error(id/(stimulus * length)), data = fhch)

aov_4(log_rt ~ task * stimulus * length + (stimulus * length|id), data = fhch)
## equivalent: aov_4(log_rt ~ task  + (stimulus * length|id), data = fhch)

# the three calls return the same ANOVA table:
#> Warning: More than one observation per design cell, aggregating data using `fun_aggregate = mean`.
#> To turn off this warning, pass `fun_aggregate = mean` explicitly.
#> Contrasts set to contr.sum for the following variables: task
#> Anova Table (Type 3 tests)
#> 
#> Response: log_rt
#>                 Effect          df  MSE          F   ges p.value
#> 1                 task       1, 43 0.23  13.38 ***  .221   <.001
#> 2             stimulus       1, 43 0.01 173.25 ***  .173   <.001
#> 3        task:stimulus       1, 43 0.01  87.56 ***  .096   <.001
#> 4               length 1.83, 78.64 0.00  18.55 ***  .008   <.001
#> 5          task:length 1.83, 78.64 0.00       1.02 <.001    .358
#> 6      stimulus:length 1.70, 72.97 0.00       1.91 <.001    .162
#> 7 task:stimulus:length 1.70, 72.97 0.00       1.21 <.001    .298
#> ---
#> Signif. codes:  0 '***' 0.001 '**' 0.01 '*' 0.05 '+' 0.1 ' ' 1
#> 
#> Sphericity correction method: GG

Plotting with afex_plot

ANOVA models can be used for plotting via afex_plot:

a <- aov_ez("id", "log_rt", fhch, between = "task", within = c("stimulus", "length"))
#> Warning: More than one observation per design cell, aggregating data using `fun_aggregate = mean`.
#> To turn off this warning, pass `fun_aggregate = mean` explicitly.
afex_plot(a, "task", "stimulus", "length")
#> Warning: Panel(s) show a mixed within-between-design.
#> Error bars do not allow comparisons across all means.
#> Suppress error bars with: error = "none"

afex_plot returns a ggplot2 plot object which allows simple customization:

library("ggplot2")
afex_plot(a, "task", "stimulus", "length") + 
  theme_bw()
#> Warning: Panel(s) show a mixed within-between-design.
#> Error bars do not allow comparisons across all means.
#> Suppress error bars with: error = "none"

Follow-up Tests with emmeans

Follow-up tests with emmeans need to be specified in two steps.

  1. Decide which factors of model should be involved in tests. Use these factors to set-up reference grid of marginal means using emmeans().
  2. Specify set of tests on reference grid from step 1. Either custom contrasts as a list and using contrast() or a convenience function such as pairs().
library("emmeans")
## set up reference grid using only length
em1 <- emmeans(a, "length")
em1
#>  length  emmean     SE df lower.CL upper.CL
#>  X4     -0.1087 0.0299 43   -0.169 -0.04834
#>  X5     -0.0929 0.0296 43   -0.153 -0.03310
#>  X6     -0.0653 0.0290 43   -0.124 -0.00679
#> 
#> Results are averaged over the levels of: task, stimulus 
#> Confidence level used: 0.95

## test all pairwise comparisons on reference grid:
pairs(em1)
#>  contrast estimate      SE df t.ratio p.value
#>  X4 - X5   -0.0159 0.00768 43  -2.065  0.1092
#>  X4 - X6   -0.0434 0.00782 43  -5.555  <.0001
#>  X5 - X6   -0.0276 0.00602 43  -4.583  0.0001
#> 
#> Results are averaged over the levels of: task, stimulus 
#> P value adjustment: tukey method for comparing a family of 3 estimates

## only test specified tests
con <- list(
  "4vs5" = c(-1, 1, 0),
  "5vs6" = c(0, -1, 1)
)
contrast(em1, con, adjust = "holm")
#>  contrast estimate      SE df t.ratio p.value
#>  4vs5       0.0159 0.00768 43   2.065  0.0449
#>  5vs6       0.0276 0.00602 43   4.583  0.0001
#> 
#> Results are averaged over the levels of: task, stimulus 
#> P value adjustment: holm method for 2 tests

Mixed Models

Function mixed() fits a mixed model with lme4::lmer (or lme4::glmer if a family argument is passed) and then calculates p-values for fixed effects model terms using a variety of methods. The formula to mixed needs to be the same as in a call to lme4::lmer. The default method for calculation of p-values is 'S' (Satterthwaite) which only works for linear mixed models (i.e., no family argument). A similar method that provides a somewhat better control of Type I errors for small data sets is 'KR' (Kenward-Roger), but it can require considerable RAM and time. Other methods are , similar to 'KR' but requires less RAM), 'PB' (parametric bootstrap), and 'LRT' (likelihood-ratio test).

More examples are provided in the vignette, here we use the same example data as above, the lexical decision and word naming latencies collected by Freeman et al. (2010). To avoid long computation times we only consider the two factors task and length (omitting stimulus is probably not a fully sensible model). Because mixed models easily allow it, we will consider crossed-random effects for participants (id) and items (tem).

library("afex")
# examples data set with both within- and between-subjects factors (see ?fhch2010)
data("fhch2010", package = "afex")
fhch <- fhch2010[ fhch2010$correct,] # remove errors
str(fhch2010) # structure of the data
#> 'data.frame':    13222 obs. of  10 variables:
#>  $ id       : Factor w/ 45 levels "N1","N12","N13",..: 1 1 1 1 1 1 1 1 1 1 ...
#>  $ task     : Factor w/ 2 levels "naming","lexdec": 1 1 1 1 1 1 1 1 1 1 ...
#>  $ stimulus : Factor w/ 2 levels "word","nonword": 1 1 1 2 2 1 2 2 1 2 ...
#>  $ density  : Factor w/ 2 levels "low","high": 2 1 1 2 1 2 1 1 1 1 ...
#>  $ frequency: Factor w/ 2 levels "low","high": 1 2 2 2 2 2 1 2 1 2 ...
#>  $ length   : Factor w/ 3 levels "4","5","6": 3 3 2 2 1 1 3 2 1 3 ...
#>  $ item     : Factor w/ 600 levels "abide","acts",..: 363 121 202 525 580 135 42 368 227 141 ...
#>  $ rt       : num  1.091 0.876 0.71 1.21 0.843 ...
#>  $ log_rt   : num  0.0871 -0.1324 -0.3425 0.1906 -0.1708 ...
#>  $ correct  : logi  TRUE TRUE TRUE TRUE TRUE TRUE ...

For the random-effects grouping factors we begin with the maximal random effect structure justified by the design (see Barr, Levy, Scheepers, & Tily, 2013). In this case this is by-subject random intercepts and by-subjects random slopes for stimulus and by-item random intercepts and by-item random slopes for task.

m1 <- mixed(log_rt ~ task * length + (length | id) + (task | item), 
            fhch)
#> Contrasts set to contr.sum for the following variables: task, length, id, item
#> boundary (singular) fit: see help('isSingular')

Fitting this model produces a critical convergence warning, that the fit is singular. This warning usually indicates that the data does not provide enough information for the request random effect parameters. In a real analysis it would therefore be a good idea to iteratively reduce the random effect structure until the warning disappears. A good first step would be to remove the correlations among random effect terms as shown below.

This warning is also shown if we simply print the model object, but not if we call the nice() method.

m1
#> Warning: lme4 reported (at least) the following warnings for 'full':
#>   * boundary (singular) fit: see help('isSingular')
#> Mixed Model Anova Table (Type 3 tests, S-method)
#> 
#> Model: log_rt ~ task * length + (length | id) + (task | item)
#> Data: fhch
#>        Effect        df         F p.value
#> 1        task  1, 44.80 13.47 ***   <.001
#> 2      length 2, 325.78   6.03 **    .003
#> 3 task:length 2, 303.23      0.33    .722
#> ---
#> Signif. codes:  0 '***' 0.001 '**' 0.01 '*' 0.05 '+' 0.1 ' ' 1
nice(m1)
#> Mixed Model Anova Table (Type 3 tests, S-method)
#> 
#> Model: log_rt ~ task * length + (length | id) + (task | item)
#> Data: fhch
#>        Effect        df         F p.value
#> 1        task  1, 44.80 13.47 ***   <.001
#> 2      length 2, 325.78   6.03 **    .003
#> 3 task:length 2, 303.23      0.33    .722
#> ---
#> Signif. codes:  0 '***' 0.001 '**' 0.01 '*' 0.05 '+' 0.1 ' ' 1

If we call the anova() method a slightly different output is shown in which the p-values are not rounded in the same way and the warning is shown again.

anova(m1)
#> Warning: lme4 reported (at least) the following warnings for 'full':
#>   * boundary (singular) fit: see help('isSingular')
#> Mixed Model Anova Table (Type 3 tests, S-method)
#> 
#> Model: log_rt ~ task * length + (length | id) + (task | item)
#> Data: fhch
#>             num Df  den Df       F    Pr(>F)    
#> task             1  44.797 13.4692 0.0006426 ***
#> length           2 325.775  6.0255 0.0026940 ** 
#> task:length      2 303.227  0.3263 0.7218472    
#> ---
#> Signif. codes:  0 '***' 0.001 '**' 0.01 '*' 0.05 '.' 0.1 ' ' 1

We can also get the default lme4 output if we call the summary method. However, note that in contrast to the previous methods, results are shown for factor-levels and not model-terms which is usually not interpretable for factors with more than two levels. This is the case for length here. The problem is that factors with $k$ levels are mapped to $k-1$ parameters and at the same time the intercept represent the (unweighted) grand mean. This means that factor-levels cannot be mapped in a 1-to-1 manner to the parameters and thus cannot be uniquely interpreted.

summary(m1)
#> Linear mixed model fit by REML. t-tests use Satterthwaite's method [
#> lmerModLmerTest]
#> Formula: log_rt ~ task * length + (length | id) + (task | item)
#>    Data: data
#> 
#> REML criterion at convergence: 7624.2
#> 
#> Scaled residuals: 
#>     Min      1Q  Median      3Q     Max 
#> -5.9267 -0.5900 -0.1018  0.4789  5.2673 
#> 
#> Random effects:
#>  Groups   Name        Variance  Std.Dev. Corr       
#>  item     (Intercept) 0.0115702 0.10756             
#>           task1       0.0104587 0.10227  0.47       
#>  id       (Intercept) 0.0374050 0.19340             
#>           length1     0.0003297 0.01816   0.16      
#>           length2     0.0001009 0.01005   0.11 -0.96
#>  Residual             0.0925502 0.30422             
#> Number of obs: 12960, groups:  item, 600; id, 45
#> 
#> Fixed effects:
#>                 Estimate Std. Error         df t value Pr(>|t|)    
#> (Intercept)    -0.089098   0.029468  44.989068  -3.024 0.004117 ** 
#> task1          -0.108035   0.029437  44.797243  -3.670 0.000643 ***
#> length1        -0.020756   0.007810 226.902599  -2.658 0.008425 ** 
#> length2        -0.003746   0.007467 380.122063  -0.502 0.616214    
#> task1:length1   0.005719   0.007569 206.633789   0.756 0.450736    
#> task1:length2  -0.004627   0.007214 353.115359  -0.641 0.521661    
#> ---
#> Signif. codes:  0 '***' 0.001 '**' 0.01 '*' 0.05 '.' 0.1 ' ' 1
#> 
#> Correlation of Fixed Effects:
#>             (Intr) task1  lngth1 lngth2 tsk1:1
#> task1        0.118                            
#> length1      0.056  0.007                     
#> length2      0.021  0.002 -0.526              
#> tsk1:lngth1  0.007  0.058  0.329 -0.173       
#> tsk1:lngth2  0.003  0.022 -0.174  0.349 -0.528
#> optimizer (nloptwrap) convergence code: 0 (OK)
#> boundary (singular) fit: see help('isSingular')

Reducing the Random Effect Structure

Because of the singular fit warning, we reduce the random effect structure. Usually a good starting point is removing the correlations among the random effects parameters. This can be done in afex::mixed even for factors by combining the double bar notation || with expand_re = TRUE. We do so for both random effects terms.

m2 <- mixed(log_rt ~ task * length + (length || id) + (task || item), 
            fhch, expand_re = TRUE)
#> Contrasts set to contr.sum for the following variables: task, length, id, item
#> boundary (singular) fit: see help('isSingular')

However, the singular fit warning remains. We therefore inspect the random effect estimates to see which random effect parameter is estimated to be near to zero.

summary(m2)$varcor
#>  Groups   Name        Std.Dev.  
#>  item     re2.task1   1.0119e-01
#>  item.1   (Intercept) 1.0685e-01
#>  id       re1.length2 3.1129e-06
#>  id.1     re1.length1 1.2292e-02
#>  id.2     (Intercept) 1.9340e-01
#>  Residual             3.0437e-01

As shown above, one parameter of the by-participant random slope for length is estimated to be almost zero, re1.length2. We therefore remove the by-participant random slope for length in the next model which does not show any convergence warnings.

m3 <- mixed(log_rt ~ task * length + (1 | id) + (task || item), 
            fhch, expand_re = TRUE)
#> Contrasts set to contr.sum for the following variables: task, length, id, item
m3
#> Mixed Model Anova Table (Type 3 tests, S-method)
#> 
#> Model: log_rt ~ task * length + (1 | id) + (task || item)
#> Data: fhch
#>        Effect        df         F p.value
#> 1        task  1, 44.74 13.52 ***   <.001
#> 2      length 2, 597.20   6.67 **    .001
#> 3 task:length 2, 592.82      0.40    .668
#> ---
#> Signif. codes:  0 '***' 0.001 '**' 0.01 '*' 0.05 '+' 0.1 ' ' 1

Plotting with afex_plot

Objects returned by mixed can be used for plotting with afex_plot. However, two things need to be considered.

  • The id argument of afex_plot allows specifying over which random effects grouping factors the data plotted in the background should be averaged over. Per default this uses all random effects grouping factors. In the present case this would mean that all data points are shown resulting in a very busy plot. When choosing only one of the random effects grouping factor, data points in the background show average response for each level of that factor. For example, when setting id = "id" here each data point in the background shows the mean log_rt of one participant (i.e., level of id).
  • Estimated marginal means in the foreground are estimated via emmeans which per default attempts to estimate the degrees of freedom using the expensive Kenward-Roger method unless the number of data points is high (as here). This can produce quite some status messages (not shown here). Use emmeans::emm_options(lmer.df = "asymptotic") to suppress this calculation.
library("ggplot2")
## all data points shown
afex_plot(m3, "task", "length") + 
  theme_bw()

## data points show IDs
afex_plot(m3, "task", "length", id = "id") + 
  theme_bw()

## data points show items
afex_plot(m3, "task", "length", id = "item") + 
  theme_bw()

Follow-up Tests with emmeans

Follow-up tests with emmeans need to be specified in two steps.

  1. Decide which factors of model should be involved in tests. Use these factors to set-up reference grid of marginal means using emmeans().
  2. Specify set of tests on reference grid from step 1. Either custom contrasts as a list and using contrast() or a convenience function such as pairs().

For mixed models, emmeans attempts to estimate the degrees of freedom. The method can be set via emm_options(lmer.df = ...). Here we use "asymptotic" which does not estimate the degrees of freedom, but sets them to infinity.

library("emmeans")
emm_options(lmer.df = "asymptotic")
## set up reference grid using only length
em2 <- emmeans(m3, "length")
#> NOTE: Results may be misleading due to involvement in interactions
em2
#>  length  emmean     SE  df asymp.LCL asymp.UCL
#>  4      -0.1099 0.0304 Inf    -0.169  -0.05040
#>  5      -0.0924 0.0304 Inf    -0.152  -0.03296
#>  6      -0.0642 0.0304 Inf    -0.124  -0.00469
#> 
#> Results are averaged over the levels of: task 
#> Degrees-of-freedom method: asymptotic 
#> Confidence level used: 0.95

## test all pairwise comparisons on reference grid:
pairs(em2)
#>  contrast          estimate     SE  df z.ratio p.value
#>  length4 - length5  -0.0175 0.0126 Inf  -1.384  0.3495
#>  length4 - length6  -0.0457 0.0126 Inf  -3.618  0.0009
#>  length5 - length6  -0.0282 0.0126 Inf  -2.238  0.0649
#> 
#> Results are averaged over the levels of: task 
#> Degrees-of-freedom method: asymptotic 
#> P value adjustment: tukey method for comparing a family of 3 estimates

## only test specified tests
con <- list(
  "4vs5" = c(-1, 1, 0),
  "5vs6" = c(0, -1, 1)
)
contrast(em2, con, adjust = "holm")
#>  contrast estimate     SE  df z.ratio p.value
#>  4vs5       0.0175 0.0126 Inf   1.384  0.1665
#>  5vs6       0.0282 0.0126 Inf   2.238  0.0504
#> 
#> Results are averaged over the levels of: task 
#> Degrees-of-freedom method: asymptotic 
#> P value adjustment: holm method for 2 tests

References

Barr, D. J., Levy, R., Scheepers, C., & Tily, H. J. (2013). Random effects structure for confirmatory hypothesis testing: Keep it maximal. Journal of Memory and Language, 68(3), 255-278. https://doi.org/10.1016/j.jml.2012.11.001

Freeman, E., Heathcote, A., Chalmers, K., & Hockley, W. (2010). Item effects in recognition memory for words. Journal of Memory and Language, 62(1), 1-18. https://doi.org/10.1016/j.jml.2009.09.004

Code of Conduct

Please note that afex is released with a Contributor Code of Conduct. By contributing to this project, you agree to abide by its terms.

afex's People

Contributors

crsh avatar jcpsantiago avatar jemus42 avatar jonathon-love avatar mariusbarth avatar mattansb avatar pablobernabeu avatar rvlenth avatar seblammers avatar singmann avatar teunbrand avatar wjhopper avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

afex's Issues

Inconsistent Ancova results

Hi,
I will start by saying that Afex made my life and other lab members life really easy and we are really grateful for your work.

In respect to the current issue, I have been running Ancova on my data using the following code:

anova.mRT.fit<- aov_ez("Subject","mRT",alc_vs_ctrl,
                                            between = "Alcohol", within = c("Congruency","Distance"),
                                            anova_table = list(es = "pes"),
                                            covariate = c("mograde","wcigpday")
)

and the results I got were as following:
image
There are few things that i'm not sure about their meaning,
a. What is the meaning ofa signifcant interaction with one of my covraites.
b. When I ran the same analysis on JASP I got different results :
image

P.S
Both Jasp (Version 0.9.0.1) and Afex (0.21-2) versions were updated before execution.

Hope you can help me figure out what going on,
Mickey

aov_car does not cope with column names with spaces in them (or other special chars)

data <- list("dependent" = rnorm(100), "RM Factor 1" = factor(rep(c("Level 1", "Level 2"), 50)), "subject" = factor(rep(1:50, each = 2)))

attr(data, 'row.names') <- seq_len(length(data[[1]]))
attr(data, 'class') <- 'data.frame'

formula <- as.formula("dependent ~ `RM Factor 1` + Error(subject/(`RM Factor 1`))")

afex::aov_car(formula, data)

Observed and df correction attributes for nice data.frames

Hi Henrik,

I'm currently working on refining the support of afex_aov objects in my package papaja. It's already a pretty seamless integration, however, there are some redundancies for options that users set when calling aov_car. Some options have to be set again in papaja functions because there is no way of knowing the original parameters. As far as I can tell, it is, e.g., impossible to deduce how df were corrected in within-subject designs or which factors were observed.

What do you think about adding these parameters as attributes to the anova_table as I have done in my previous pull request with the p.adjust.method? I'd be happy to do this myself but I wanted to check with you first before getting started.

HF epsilon

When the HF epsilon is high and HF is set as the correction type, aov_ez fails with this error message:

Error in if (any(tmp[["pval.adjustments"]][, "HF eps"] > 1)) warning("HF eps > 1 treated as 1",  : 
  missing value where TRUE/FALSE needed

afex_plot appears to be broken

Dear Henrik,

today I attempted a very simple analysis:

aov_fit = aov_ez(data=data, id="id", dv="psd", between="Group", within=c("Time", "Frequency"))

afex_plot(aov_fit, x='Time', trace='Group', panel='Frequency')

which throws the following error:
Error in ref_grid(object, ...) :
Can't handle an object of class “afex_aov”
Use help("models", package = "emmeans") for information on supported models.

I also attempted to reproduce the plots from your example here:
https://cran.r-project.org/web/packages/afex/vignettes/afex_anova_example.html

and afex_plot broke down given the same error.

Library versions:
afex version: ‘0.23.0’
emmeans version: ‘1.3.5’
ggplot2 version: ‘3.1.1’

What might be at issue here?

Regards,
Stefan

Cannot load package, possibly because of emmeans

Hi Henrik,

When I try to load the afex library, I get the following error:

library(afex)
Error: package or namespace load failed for ‘afex’:
.onLoad failed in loadNamespace() for 'afex', details:
call: NULL
error: '.emm_register' is not an exported object from 'namespace:emmeans'

I checked that:

  • I have the latest version of emmeans and it works.
  • I have the latest version of namespace, nothing to update there.
  • I have the latest version of r, nothing to update there.
  • I did not find anyone having a similar issue here.
  • It could be the case the emmeans update from September 12th is behind this. However, I tried installing older versions of emmeans by doing things like the code below. But it did not work.
  • I also tried to installing older verision of afex by a similar procedure but I got an error saying that afex.rdb is corrupt

remove.packages(package = "emmeans")
packageurl <- "https://cran.r-project.org/src/contrib/Archive/emmeans/emmeans_1.3.4.tar.gz"
install.packages(packageurl, repos=NULL, type="source")

Many thanks.
Nico.

Argument order in aov_ez

Is there a specific reason why id is the first argument in aov_ez, and data is the third?

It would make more sense to me if data was the first argument, because then it would fit nicely into pipelines like

data %>%
  dplyr::filter(some_filtering_here) %>%
  aov_ez("id", "dv", further_arguments_here)

instead of now

data %>%
  dplyr::filter(some_filtering_here) %>%
  aov_ez("id", "dv", ., further_arguments_here)

results of lmer_alt depend on contrast-type

When using lmer_alt for the ability to use || with factors, the results vary depending the type of factor contrasts used:

library(afex)

set_treatment_contrasts()
#> setting contr.treatment globally: options(contrasts=c('contr.treatment', 'contr.poly'))

fit_t <- lmer_alt(value ~ phase + (phase || id),
                  data = obk.long,
                  check_contrasts = FALSE, expand_re = TRUE)

set_effects_contrasts()
#> setting contr.sum globally: options(contrasts=c('contr.sum', 'contr.poly'))

fit_e <- lmer_alt(value ~ phase + (phase || id),
                  data = obk.long,
                  check_contrasts = FALSE, expand_re = TRUE)


anova(fit_t)
#> Type III Analysis of Variance Table with Satterthwaite's method
#>       Sum Sq Mean Sq NumDF  DenDF F value    Pr(>F)    
#> phase 46.155  23.078     2 16.765  14.036 0.0002623 ***
#> ---
#> Signif. codes:  0 '***' 0.001 '**' 0.01 '*' 0.05 '.' 0.1 ' ' 1
anova(fit_e)
#> Type III Analysis of Variance Table with Satterthwaite's method
#>       Sum Sq Mean Sq NumDF  DenDF F value    Pr(>F)    
#> phase  45.04   22.52     2 21.527  13.856 0.0001356 ***
#> ---
#> Signif. codes:  0 '***' 0.001 '**' 0.01 '*' 0.05 '.' 0.1 ' ' 1

I'm not sure if this is an intended behavior, but I didn't expect this to happen*. Should this happen? If so, which option is the preferred one (or what is the underlying difference)?

(* in the above example the results only vary slightly, but I came across this in real world data where the differences was very big - like conclusion changing big, but unfortunately I cannot share the data as it is not mine)

Error when passing formula to mixed() with more than 60 characters

I first noticed this problem within my own data, but have since been able to replicate it with a built-in dataset.

I can't quite figure out the pattern, but here's what I've found so far; when specifying a formula with up to four fixed terms, afex's mixed function works as expected:

library(afex)
library(languageR)

data(lexdec, package = "languageR")

mixed(RT ~ Correct*Trial + PrevType * meanWeight + (1|Subject) + (1|Word), data = lexdec)
mixed(RT ~ Correct*Trial + PrevType * meanWeight + NativeLanguage + Length + (1|Subject) + (1|Word), data = lexdec)
mixed(RT ~ Correct*Trial + PrevType * meanWeight + NativeLanguage*Length + (1|Subject) + (1|Word), data = lexdec)

However, when specifying a formula with five or more fixed terms, it seems that mixed is unable to parse any term from the fifth onward, and an error is thrown up as a result:

 mixed(RT ~ Correct + Correct:Trial + PrevType * meanWeight + NativeLanguage + Length + (1|Subject) + (1|Word), data = lexdec)
Error in parse(text = x, keep.source = FALSE) : 
  <text>:2:7: unexpected symbol
1: RT~Correct + Correct:Trial + PrevType * meanWeight + NativeLanguage + +(1 | Subject) + (1 | Word)
2: RT    Length
         ^

mixed(RT ~ Correct + Trial + PrevType * meanWeight  + NativeLanguage * Length + Frequency + (1|Subject) + (1|Word), data = lexdec)
Error in parse(text = x, keep.source = FALSE) : 
  <text>:2:7: unexpected symbol
1: RT~Correct + Trial + PrevType * meanWeight + NativeLanguage * Length + +(1 | Subject) + (1 | Word)
2: RT    Frequency
         ^

mixed(RT ~ Correct + Trial + PrevType + meanWeight  + NativeLanguage * Length + Frequency + PrevType:meanWeight + (1|Subject) + (1|Word), data = lexdec)
Error in parse(text = x, keep.source = FALSE) : 
  <text>:2:7: unexpected symbol
1: RT~Correct + Trial + PrevType + meanWeight + NativeLanguage * Length + +(1 | Subject) + (1 | Word)
2: RT    Frequency
         ^

In cases where a working formula is specified, this warning message always appears:

In addition: Warning messages:
1: In stri_c(..., sep = sep, collapse = collapse, ignore_null = TRUE) :
  longer object length is not a multiple of shorter object length

lmer is still working as expected:

lmer(RT ~ Correct + Trial + PrevType * meanWeight + 
+           Frequency + NativeLanguage * Length + (1|Subject) + (1|Word), data = lexdec)
Linear mixed model fit by REML ['lmerMod']
Formula: RT ~ Correct + Trial + PrevType * meanWeight + Frequency + NativeLanguage *      Length + (1 | Subject) + (1 | Word)
   Data: lexdec
REML criterion at convergence: -972.8595
Random effects:
 Groups   Name        Std.Dev.
 Word     (Intercept) 0.04748 
 Subject  (Intercept) 0.13547 
 Residual             0.16831 
Number of obs: 1659, groups:  Word, 79; Subject, 21
Fixed Effects:
               (Intercept)            Correctincorrect                       Trial                PrevTypeword                  meanWeight  
                  6.486675                   -0.064751                   -0.000245                   -0.009240                    0.038132  
                 Frequency         NativeLanguageOther                      Length     PrevTypeword:meanWeight  NativeLanguageOther:Length  
                 -0.048023                    0.054975                    0.003433                   -0.020189                    0.017017

All these formulas used to work in a previous version of afex (afraid I don't know exactly what I was running... whatever the most up-to-date version was in March 2015).

SessionInfo() can be seen here.

EDIT: I can confirm that mixed gives the expected output for the following formula when using afex 0.13-145 from CRAN, though I do get an error regarding object length, as above:

mixed(RT ~ Correct + Trial + PrevType * meanWeight + 
                    Frequency + NativeLanguage * Length + (1|Subject) + (1|Word), data = lexdec)
Contrasts set to contr.sum for the following variables: Correct, PrevType, NativeLanguage, Subject, Word
Numerical variables NOT centered on 0 (i.e., interpretation of all main effects might be difficult if in interactions): Trial, meanWeight, Frequency, Length
Fitting 10 (g)lmer() models:
[..........]
Obtaining 9 p-values:
[.........]
                 Effect     F ndf     ddf F.scaling p.value
1               Correct  8.15   1 1627.73      1.00    .004
2                 Trial  7.57   1 1592.43      1.00    .006
3              PrevType  0.17   1 1605.39      1.00     .68
4            meanWeight 14.85   1   75.39      1.00   .0002
5             Frequency 56.53   1   76.08      1.00  <.0001
6        NativeLanguage  0.70   1   27.11      1.00     .41
7                Length  8.70   1   75.83      1.00    .004
8   PrevType:meanWeight  6.18   1 1601.18      1.00     .01
9 NativeLanguage:Length 14.24   1 1555.49      1.00   .0002
Warning message:
In stri_c(..., sep = sep, collapse = collapse, ignore_null = TRUE) :
  longer object length is not a multiple of shorter object length

`sig.symbols` currently ignored in calls to `aov_car()`

Currently, when calling aov_car() passing sig.symbols to in the anova_table list has no effect. This is because print.afex_aov() passes the anova_table object to nice() and sig.symbols is lost. A straight forward solution for this would be to add another attribute to either the entire afex_aov object or to anova_table (I would probably prefer the latter). nice() could then use the attribute value if nothing is explicitly passed when calling the function. I think it would also be handy to add sig.symbols to afex_options() so they could be set once globally for all analyses. Any thoughts on this?

One other thing I was wondering about: print.afex_aov() currently does not print the sig.symbol-legend (e.g., Signif. codes: 0 ‘***’ 0.001 ‘**’ 0.01 ‘*’ 0.05 ‘.’ 0.1 ‘ ’ 1) but the legend is printed by print.anova(), which is used for the anova_table object. Do you think this is something to standardize while working on this?

Is it possible to get effect sizes for the omnibus F-test returned by `mixed`?

Some journals request effect sizes to be included in the analysis. I don't know if this is possible, but can a specialised effect statistic (such as eta-squared) be returned alongside the F-test? Effect sizes such as standardised beta in a LMM table are not interpretable when using sum contrast coding (especially when number of levels of a factor are >= 3).

How are unbalanced designs dealt with?

Hi Henrik,
Was working on an example for a stats class showing how unbalanced designs in ANOVA can cause "fake" effects, but ran into some differences between afex's aov_4 and base-stats's aov:

I simulated some 2*2 between subject data with one main effect and one interaction when examining the means (the data can be found here), but with unequal cell sizes, causing a confounding between cell placement between the factors.

> some_data <- read.csv(choose.files())
> 
> cell_data <- split(some_data$y,interaction(some_data$A,some_data$B))
> unlist(lapply(cell_data,mean)) # the means for each cell - no main effect for A
a1.b1 a2.b1 a1.b2 a2.b2 
    3     1     2     4 
> unlist(lapply(cell_data,length)) # the cell sizes - A and B are confounded
a1.b1 a2.b1 a1.b2 a2.b2 
    5     3     5     7 

While aov showed the expected artifact of an effect for A:

> stats_fit <- aov(y ~ A * B, data = some_data)
> car::Anova(stats_fit,type = 3)
Anova Table (Type III tests)

Response: y
            Sum Sq Df F value    Pr(>F)    
(Intercept) 45.000  1  45.000 5.026e-06 ***
A            7.500  1   7.500 0.0145711 *  
B            2.500  1   2.500 0.1334103    
A:B         18.261  1  18.261 0.0005822 ***
Residuals   16.000 16                      
---
Signif. codes:  0 ‘***’ 0.001 ‘**’ 0.01 ‘*’ 0.05 ‘.’ 0.1 ‘ ’ 1

aov_4 did not:

> library(afex)
> afex_fit <- aov_4(y ~ A * B + (1|id), data = some_data)
Contrasts set to contr.sum for the following variables: A, B
> afex_fit
Anova Table (Type 3 tests)

Response: y
  Effect    df  MSE         F    ges p.value
1      A 1, 16 1.00      0.00 <.0001    >.99
2      B 1, 16 1.00    4.57 *    .22     .05
3    A:B 1, 16 1.00 18.26 ***    .53   .0006
---
Signif. codes:  0 ‘***’ 0.001 ‘**’ 0.01 ‘*’ 0.05 ‘+’ 0.1 ‘ ’ 1

I would expect aov_4 to "fail" in the same manner as aov. Could you explain where these differences stem from? (asking for myself, but also for my students).

Thanks!

aov_ez fails with `dplyr` data.frame

require(afex)
require(dplyr)

data(md_12.1)
aov_ez("id", "rt", md_12.1, within = c("angle", "noise"), 
       anova_table=list(correction = "none", es = "none"))
##        Effect    df     MSE         F p.value
## 1       angle 2, 18 3560.00 40.72 ***  <.0001
## 2       noise  1, 9 8460.00 33.77 ***   .0003
## 3 angle:noise 2, 18 1160.00 45.31 ***  <.0001

md2 <- tbl_df(md_12.1)
aov_ez("id", "rt", md2, within = c("angle", "noise"), 
       anova_table=list(correction = "none", es = "none"))
## Error in aov_car(formula = as.formula(formula), data = data, fun.aggregate = fun.aggregate,  : 
##   dv needs to be numeric.

nice() ANOVA table MSE report

Hello,

first of all, thanks a lot for creating the afex package. I am using it a lot to compute
all of my ANOVAs or ANCOVAs. I have a question / suggestion with regard to the ANOVA
table that is produced when conducting an ANOVA with afex. When I compute a
multi-factorial ANOVA with several between-subjects factors, I get a table like this:

> # ANOVA example using Iris data

> data(iris)
> iris$id <- 1:nrow(iris)
> iris$rndFactor <- factor(rep(sample(3), 50)) # some second random between-subjects factor
> aoov <-  afex::aov_ez("id", "Sepal.Length", iris, between = c("Species", "rndFactor"))
> nice(aoov)
Anova Table (Type 3 tests)

Response: Sepal.Length
             Effect     df  MSE          F   ges p.value
1           Species 2, 141 0.27 119.83 ***   .63  <.0001
2         rndFactor 2, 141 0.27       0.06 .0008     .95
3 Species:rndFactor 4, 141 0.27       1.47   .04     .21

In this case, the column MSE contains the mean squared error three times. Is this
intended behavior? Maybe it would be more appropriate if the mean squared estimate
for each between-subject factor is reported in this column instead? I am asking because
when using rmarkdown I can directly use the nice() table in a pdf report, and
in this case I do not like to use the MSE column as it is currently implemented. But
maybe I am missing something and this is in fact intended behavior.

Best regards and thanks a lot,
Martin

Mapping different factors on e.g. color and shape

As briefly explained on Twitter: I would like to plot one factor on color and another one on shape etc., allowing to incorporate additional factors into one graph (yes, this opens the door to overplotting but might be useful anyhow). Would make this even more powerful than it already is.

Label change on the trace factor in a 3 way interaction plot

Hi,

I'm trying to modify labels on a 3 way interaction plot. I've been able to modify the x and y
with"
labs(y="DTF (days after planting)", x="Cytoplasm haplotype")
But I can't find the way to modify the factor that would be in trace=

Any idea?

Cannot load mixed objects fitted in older versions

When constructing a model with an old version, e.g.;

require(devtools)
dev_mode()
install_url("https://cran.rstudio.com/src/contrib/Archive/afex/afex_0.13-145.tar.gz")
require(afex)
data(obk.long)
m1 <- mixed(value ~ treatment * phase + (1|id), obk.long)
save(m1, file = "lmm_test.rda")

It cannot be opened in the latest version (after restarting R and loading the latest afex):

require(afex)
load("lmm_test.rda")
m1
## Error in if (attr(object, "method") == "KR") { : 
##  argument is of length zero

(probably a different error if fitted with LRT!!)

emmeans maybe a dependency not a suggested package?

Hi afex dev team,

We tried to install the afex package but that failed with the following error:
Error: package or namespace load failed for ‘afex’: .onLoad failed in loadNamespace() for 'afex', details: call: NULL error: '.emm_register' is not an exported object from 'namespace:emmeans'

Installing package lme4 mannually (as it was not installed as a dependency automatically) did not help, but installing emmeans did solve the issue, though it is listed as a suggested package.

Versions currently installed:
R 3.4.4
afex 0.25.1
lme4 1.1.21
emmeans 1.4.2
Running on Ubuntu 18.04.3 LTS

allFit does not work with (0+var|group) and expand_re=TRUE

I'm using the expand_re=TRUE option for automatically converting my factors into vectors in the random effects structure which works fine.

However, passing the full model to allFit does not work if the intercept has been removed from the random effects structure, using the (0 + x | group) syntax. Instead, each optimizer returns an error message that the automatically generated vector hasn't been found. Keeping the intercept in does work just fine.

a minimal reproducible example (using example from afex::allFit):

library(afex)
data("sk2011.2")
sk2_aff <- droplevels(sk2011.2[sk2011.2$what == "affirmation",])

# the following works - taken from example section
sk_m2 <- mixed(response ~ instruction*inference*type+(inference*type||id), sk2_aff,
               expand_re = TRUE)
allFit(sk_m2$full.model)

# but this one doesn't pass the expanded vectors to allFit:
sk_m3 <- mixed(response ~ instruction * inference * type + (0 + inference | id), sk2_aff,
               expand_re = TRUE) # runs just fine
allFit(sk_m3$full.model) # runs, but returns same error for all optimizers: <simpleError in eval(expr, envir, enclos): object 're1.inferenceMP' not found>

Suggestion: three decimal places for p-values

Hello!

Kudos on this convenient package! I'd like to make a suggestion--very small thing, not essential. In the version of mixed() results that features reduced decimal places (like with nice() or when you read in the model name alone), could it make sense to leave three decimal places in the p-values, instead of two places as now, in order to match the standard in psychology and neuroscience?

Best regards,
Pablo

Two sets of errors using mixed on a glmm

I have the following data:

Patient Day Cluster APP_ml
1 P54 1 High 10.656200
2 P54 2 High 4.353180
3 P54 3 High 22.294005
4 P54 4 High 8.548865
5 P54 5 High 16.959220
6 P64 1 High 9.896800
7 P64 2 High 7.637585
8 P64 3 High 9.744920
9 P64 4 High 11.187780
10 P64 5 High 11.453570
11 P70 1 Low 3.840585
12 P70 2 Low 5.226490
13 P70 3 Low 4.429120
14 P70 4 Low 8.396985
15 P70 5 Low 6.631380
19 P71 1 High 12.307895
20 P71 2 High 4.068405
21 P71 3 High 5.397355
22 P71 4 High 18.515990
23 P71 5 High 32.280115
26 P72 1 High 15.041735
27 P72 2 High 6.346605
28 P72 3 High 7.998300
29 P72 4 High 9.763905
30 P75 1 Low 2.416710
31 P75 2 Low 3.119155
32 P75 3 Low 7.542660
33 P75 4 Low 5.473295
34 P75 5 Low 6.327620
37 P76 1 Low 6.004875
38 P76 2 Low 3.365960
39 P76 3 Low 10.371425
40 P76 4 Low 4.448105
41 P77 1 Low 4.315210
42 P77 2 Low 1.353550
43 P77 3 Low 6.194725
44 P77 4 Low 5.815025
45 P77 5 Low 12.839475
48 P78 1 Low 7.068035
49 P78 2 Low 14.586095
50 P78 3 Low 23.547015
51 P78 4 Low 11.111840
52 P78 5 Low 14.548125
54 P79 1 Low 4.922730
55 P79 2 Low 6.574425
56 P79 3 Low 9.877815
57 P79 4 Low 5.966905
58 P79 5 Low 8.985520
60 P80 1 High 11.035900
61 P80 2 High 12.744550
62 P80 3 High 20.490430
63 P80 4 High 22.483855
64 P82 1 High 9.175370
65 P82 2 High 5.739085
66 P82 3 High 5.890965
67 P82 4 High 6.099800

I have the following model:
allmod.full<- glmer(APP_ml ~ Cluster * Day + (1+Day|Patient), data = APP.daytrim, family = Gamma(link = "identity"), glmerControl(optimizer = "bobyqa"))

This works nicely.

I try the following:
foo<-mixed(formula(allmod.m.trim),method="LRT",data=APP.daytrim,family=Gamma(link="identity"),options(glmerControl(optimizer = "bobyqa")))

I get the following:
Error in mixed(formula(allmod.m.trim), method = "LRT", data = APP.daytrim, :
(list) object cannot be coerced to type 'double'

So, I do this model:
allmod.full<- glmer(APP_ml ~ Cluster * Day + (1+Day|Patient), data = APP.daytrim, family = Gamma(link = "identity"))

It converges nicely, too.

So, I try this:
foo<-mixed(formula(allmod.m.trim),method="LRT",data=APP.daytrim,family=Gamma(link="identity"))

And I get this:
Warning message:
In checkConv(attr(opt, "derivs"), opt$par, ctrl = control$checkConv, :
Model failed to converge with max|grad| = 0.0264542 (tol = 0.001, component 1)

What am I doing wrong?

Problems specifying a repeated measures ANOVA with a single factor

Example data:

load(url("https://public.tadaa-data.de/data/experim"))

 head(experim)
# A tibble: 6 × 3
      ID confidence conf_time
  <fctr>      <dbl>    <fctr>
1      4         15   CONFID1
2     10         14   CONFID1
3      9         12   CONFID1
4      3         11   CONFID1
5     12         16   CONFID1
6     11         13   CONFID1

library(dplyr)
experim %>% group_by(ID, conf_time) %>% tally
# Source: local data frame [90 x 3]
# Groups: ID [?]

       ID conf_time     n
   <fctr>    <fctr> <int>
1       1   CONFID1     1
2       1   CONFID2     1
3       1   CONFID3     1
4       2   CONFID1     1
5       2   CONFID2     1
6       2   CONFID3     1
7       3   CONFID1     1
8       3   CONFID2     1
9       3   CONFID3     1
10      4   CONFID1     1

With confidence being the dependent variable, conf_time being the factor, i.e. the points of measurement, and ID the subject ID.

From reading the documentation examples and also this post, I was under the assumption that it would suffice to do the following:

aov_ez(id = "ID", dv = "confidence", data = experim, between = "conf_time")

…which yields the following error:

Error in aov_car(formula = as.formula(formula), data = data, fun_aggregate = fun_aggregate,  : 
  Following ids are in more than one between subjects condition:
4, 10, 9, 3, 12, 11, 6, 5, 8, 13, 14, 1, 15, 7, 2, 27, 25, 19, 18, 23, 21, 26, 29, 17, 20, 28, 22, 24, 16, 30

…which I don't understand. I assumed I might be misunderstanding the terms/arguments, so I tried:

aov_ez(id = "ID", dv = "confidence", data = experim, within = "conf_time")

Error in `contrasts<-`(`*tmp*`, value = if (is.ordered(idata[, i])) icontrasts[2] else icontrasts[1]) : 
  contrasts apply only to factors

…which confused me even more, as both factors are, well, factor variables.

Other thing's I've tried:

  • Converting conf_time to an ordered factor
  • Playing around with various arguments to aov_ez, e.g. type
  • Specifying the model using aov_car as aov_car(confidence ~ conf_time + Error(ID/conf_time), data = experim), with same result

Since this is the most basic design of a repeated measure ANOVA I can think of, I really don't know what else to try (incidentally, this dataset and design is part of a psychology/stats course at Uni Bremen. I'm trying to teach students how to do various styles of ANOVA in R as the course is focused on SPSS, and it's not going great so far).

Session info:

afex_options()
$check_contrasts
[1] TRUE

$correction_aov
[1] "GG"

$es_aov
[1] "ges"

$factorize
[1] TRUE

$lmer_function
[1] "lmerTest"

$method_mixed
[1] "KR"

$return_aov
[1] "afex_aov"

$sig_symbols
[1] " +"   " *"   " **"  " ***"

$type
[1] 3

devtools::session_info()
Session info ---------------------------------------------------------------------------------------
 setting  value                       
 version  R version 3.4.0 (2017-04-21)
 system   x86_64, darwin15.6.0        
 ui       RStudio (1.1.233)           
 language (EN)                        
 collate  en_US.UTF-8                 
 tz       Europe/Berlin               
 date     2017-05-17                  

Packages -------------------------------------------------------------------------------------------
 package      * version  date       source                            
 acepack        1.4.1    2016-10-29 CRAN (R 3.4.0)                    
 afex         * 0.17-8   2017-04-13 CRAN (R 3.4.0)                    
 assertthat     0.2.0    2017-04-11 CRAN (R 3.4.0)                    
 backports      1.0.5    2017-01-18 CRAN (R 3.4.0)                    
 base         * 3.4.0    2017-04-21 local                             
 base64enc      0.1-3    2015-07-28 CRAN (R 3.4.0)                    
 car            2.1-4    2016-12-02 CRAN (R 3.4.0)                    
 checkmate      1.8.2    2016-11-02 CRAN (R 3.4.0)                    
 cluster        2.0.6    2017-03-10 CRAN (R 3.4.0)                    
 coda           0.19-1   2016-12-08 CRAN (R 3.4.0)                    
 codetools      0.2-15   2016-10-05 CRAN (R 3.4.0)                    
 coin           1.1-3    2016-11-28 CRAN (R 3.4.0)                    
 colorspace     1.3-2    2016-12-14 CRAN (R 3.4.0)                    
 compiler       3.4.0    2017-04-21 local                             
 data.table     1.10.4   2017-02-01 CRAN (R 3.4.0)                    
 datasets     * 3.4.0    2017-04-21 local                             
 DBI            0.6-1    2017-04-01 CRAN (R 3.4.0)                    
 devtools       1.13.1   2017-05-13 CRAN (R 3.4.0)                    
 digest         0.6.12   2017-01-27 CRAN (R 3.4.0)                    
 dplyr        * 0.5.0    2016-06-24 CRAN (R 3.4.0)                    
 estimability * 1.2      2016-11-19 CRAN (R 3.4.0)                    
 evaluate       0.10     2016-10-11 CRAN (R 3.4.0)                    
 foreign        0.8-68   2017-04-24 CRAN (R 3.4.0)                    
 Formula        1.2-1    2015-04-07 CRAN (R 3.4.0)                    
 ggplot2        2.2.1    2016-12-30 CRAN (R 3.4.0)                    
 graphics     * 3.4.0    2017-04-21 local                             
 grDevices    * 3.4.0    2017-04-21 local                             
 grid           3.4.0    2017-04-21 local                             
 gridExtra      2.2.1    2016-02-29 CRAN (R 3.4.0)                    
 gtable         0.2.0    2016-02-26 CRAN (R 3.4.0)                    
 haven        * 1.0.0    2016-09-23 CRAN (R 3.4.0)                    
 Hmisc          4.0-3    2017-05-02 cran (@4.0-3)                     
 hms            0.3      2016-11-22 CRAN (R 3.4.0)                    
 htmlTable      1.9      2017-01-26 CRAN (R 3.4.0)                    
 htmltools      0.3.6    2017-04-28 cran (@0.3.6)                     
 htmlwidgets    0.8      2016-11-09 CRAN (R 3.4.0)                    
 jsonlite       1.4      2017-04-08 CRAN (R 3.4.0)                    
 knitr          1.15.1   2016-11-22 CRAN (R 3.4.0)                    
 lattice        0.20-35  2017-03-25 CRAN (R 3.4.0)                    
 latticeExtra   0.6-28   2016-02-09 CRAN (R 3.4.0)                    
 lazyeval       0.2.0    2016-06-12 CRAN (R 3.4.0)                    
 lme4         * 1.1-13   2017-04-19 CRAN (R 3.4.0)                    
 lmerTest       2.0-33   2016-12-03 CRAN (R 3.4.0)                    
 lsmeans      * 2.26-3   2017-05-09 CRAN (R 3.4.0)                    
 magrittr       1.5      2014-11-22 CRAN (R 3.4.0)                    
 MASS           7.3-47   2017-02-26 CRAN (R 3.4.0)                    
 Matrix       * 1.2-10   2017-04-28 CRAN (R 3.4.0)                    
 MatrixModels   0.4-1    2015-08-22 CRAN (R 3.4.0)                    
 memoise        1.1.0    2017-04-21 CRAN (R 3.4.0)                    
 methods      * 3.4.0    2017-04-21 local                             
 mgcv           1.8-17   2017-02-08 CRAN (R 3.4.0)                    
 minqa          1.2.4    2014-10-09 CRAN (R 3.4.0)                    
 modeltools     0.2-21   2013-09-02 CRAN (R 3.4.0)                    
 multcomp       1.4-6    2016-07-14 CRAN (R 3.4.0)                    
 munsell        0.4.3    2016-02-13 CRAN (R 3.4.0)                    
 mvtnorm        1.0-6    2017-03-02 CRAN (R 3.4.0)                    
 nlme           3.1-131  2017-02-06 CRAN (R 3.4.0)                    
 nloptr         1.0.4    2014-08-04 CRAN (R 3.4.0)                    
 nnet           7.3-12   2016-02-02 CRAN (R 3.4.0)                    
 parallel       3.4.0    2017-04-21 local                             
 pbkrtest       0.4-7    2017-03-15 CRAN (R 3.4.0)                    
 plyr           1.8.4    2016-06-08 CRAN (R 3.4.0)                    
 quantreg       5.33     2017-04-18 CRAN (R 3.4.0)                    
 R6             2.2.1    2017-05-10 cran (@2.2.1)                     
 RColorBrewer   1.1-2    2014-12-07 CRAN (R 3.4.0)                    
 Rcpp           0.12.10  2017-03-19 CRAN (R 3.4.0)                    
 readr          1.1.0    2017-03-22 CRAN (R 3.4.0)                    
 reshape2       1.4.2    2016-10-22 CRAN (R 3.4.0)                    
 rmarkdown      1.5.9000 2017-05-17 Github (rstudio/rmarkdown@0f89945)
 rpart          4.1-11   2017-03-13 CRAN (R 3.4.0)                    
 rprojroot      1.2      2017-01-16 CRAN (R 3.4.0)                    
 rsconnect      0.8      2017-05-08 CRAN (R 3.4.0)                    
 sandwich       2.3-4    2015-09-24 CRAN (R 3.4.0)                    
 scales         0.4.1    2016-11-09 CRAN (R 3.4.0)                    
 SparseM        1.77     2017-04-23 CRAN (R 3.4.0)                    
 splines        3.4.0    2017-04-21 local                             
 stats        * 3.4.0    2017-04-21 local                             
 stats4         3.4.0    2017-04-21 local                             
 stringi        1.1.5    2017-04-07 CRAN (R 3.4.0)                    
 stringr        1.2.0    2017-02-18 CRAN (R 3.4.0)                    
 survival       2.41-3   2017-04-04 CRAN (R 3.4.0)                    
 TH.data        1.0-8    2017-01-23 CRAN (R 3.4.0)                    
 tibble         1.3.0    2017-04-01 CRAN (R 3.4.0)                    
 tidyr        * 0.6.2    2017-05-04 CRAN (R 3.4.0)                    
 tools          3.4.0    2017-04-21 local                             
 utils        * 3.4.0    2017-04-21 local                             
 withr          1.0.2    2016-06-20 CRAN (R 3.4.0)                    
 xtable         1.8-2    2016-02-05 CRAN (R 3.4.0)                    
 yaml           2.1.14   2016-11-12 CRAN (R 3.4.0)                    
 zoo            1.8-0    2017-04-12 CRAN (R 3.4.0)  

Is it possible to coerce a "mixed" object into a "merModLmerTest" object?

In order to compute R2 for generalized linear mixed-effects models, I use to follow the procedure described in Nakagawa & Schielzeth (2013). This procedure requires to access the fixef() and getME() functions, which do not work with "mixed" objects, as shows the following error message:
Error in UseMethod("fixef") :
no applicable method for 'fixef' applied to an object of class "mixed"

Is there any possibility to coerce a "mixed" object into a "merModLmerTest" object, or an equivalent object supported by fixef()?

Nakagawa & Schielzeth_2013_MEE_General and simple method for obtaining R2 from GLMMs.pdf

Intercept-less models broken

The mixed() function fails to handle models with a suppressed intercept. Intercept-less models are useful as a way of tricking lme4 into doing multivariate analysis. (The convential trick of using cbind(incidence,size) ~ period + (1|herd) doesn't work.)

> library(afex)
> library(reshape2)
> d = melt(cbpp,id.vars=c('period','herd'))
> m = mixed(value ~ 0 + variable:period + (0+variable|herd),d)
Contrasts set to contr.sum for the following variables: variable, period, herd
Fitting 2 (g)lmer() models:
[.Error in x[, ii] : subscript out of bounds

Multivariate EMM results from aov_ez

The help page for aov_ez states:

A caveat regarding the use of emmeans concerns the assumption of sphericity for ANOVAs including within-subjects/repeated-measures factors (with more than two levels). While the ANOVA tables per default report results using the Greenhousse-Geisser correction, no such correction is available when using emmeans. This may result in anti-conservative tests.

I think this is somewhat misleading, in that it is true only because the implementation of emm_basis.aov_ez relies on the aov results. It appears that aov_ez also fits a multivariate model, which is returned in the lm member of the object. If that were actually used fully, users could obtain EMMs based on the multivariate model. Those results would not have the deficiencies mentioned above.

To illustrate, here is an example from the help page for aov_ez:

data(md_12.1)
aez <- aov_ez("id", "rt", md_12.1, within = c("angle", "noise"), 
       anova_table=list(correction = "none", es = "none"))

Here is the reference grid for the lm member of the object:

ref_grid(aez$lm)
## 'emmGrid' object with variables:
##     1 = 1
##     rep.meas = multivariate response levels: X0_absent, X0_present, X4_absent, X4_present, X8_absent, X8_present

So lets use the mult.names option to sort these out:

aez.mult <- ref_grid(aez$lm, 
    mult.levs = list(noise = c("absent", "present"), 
                     angle = c("X0", "X4", "X8")))

Now compare the results:

emmeans(aez.mult, ~ noise * angle)
## noise   angle emmean       SE df lower.CL upper.CL
## absent  X0       462 18.00000  9 421.2812 502.7188
## present X0       492 28.00000  9 428.6596 555.3404
## absent  X4       510 27.20294  9 448.4627 571.5373
## present X4       660 34.64102  9 581.6366 738.3634
## absent  X8       528 24.97999  9 471.4913 584.5087
## present X8       762 36.93237  9 678.4532 845.5468
##
## Confidence level used: 0.95 

emmeans(aez, ~ noise * angle)
## noise   angle emmean       SE    df lower.CL upper.CL
## absent  X0       462 28.97125 19.79 401.5263 522.4737
## present X0       492 28.97125 19.79 431.5263 552.4737
## absent  X4       510 28.97125 19.79 449.5263 570.4737
## present X4       660 28.97125 19.79 599.5263 720.4737
## absent  X8       528 28.97125 19.79 467.5263 588.4737
## present X8       762 28.97125 19.79 701.5263 822.4737
##
## Confidence level used: 0.95 

The predictions are the same, but the SEs and df for aez.mult are obtained from the multivariate model.

afex could provide an option so that the user may choose which analysis they want. This can be done by adding, say, a mode argument to emm_basis.afex_aov, that can have values like "multivariate" (would use the lm member like in this example) and "univariate" (the current default). See current emmeans support for such as lme objects (simple) or clm (complex) to see how this may be done. I think all you need to do in this case is to call emm_basis for the lm member and set misc$ylevs to the needed levels.

return = "merMod" doesn't return merMod object

mixed(..., return = "merMod"), and thus lmer_alt(), call lmerTest::lmer() by default and therefore return an object of class lmerModLmerTest.
According to the documentation

lmer_alt is simply a wrapper for mixed that only returns the "merMod" object and correctly uses the || notation to remove correlation among factors, but otherwise behaves like g/lmer

IMHO it would be more appropriate to fit the model via lme4::lmer() in this case. This would also save a lot of computation time as for the new lmerTest version the Hessian and derivatives needed for evaluation of degrees of freedom are computed directly within lmerTest::lmer(). And AFAICS these are only needed for calls to mixed() where return != "merMod". Besides that, merMod objects can be converted to lmerModLmerTest objects via lmerTest::as_lmerModLmerTest(object).

@singmann if this makes sense to you an easy fix would be to add mf[[1]] <- quote(lme4::lmer) after line 308 in mixed.R

Error with multiple covariates in 0.17-8

Example code:

require(psych)
require(afex)
data(msq)
aov_ez(data=msq, dv="Extraversion", id = "ID", between = "condition", 
    covariate=c("TOD", "MSQ_Time"), factorize=FALSE)

In afex 0.16-1, this works fine, but in 0.17-8, I get this error:

Error in `[.data.frame`(data, , between, drop = FALSE) : 
  undefined columns selected

It looks like the names of the covariates are being concatenated in a strange way.

Importing with rpy2

Dear afex Experts,

I am attempting to import this packaged in jupyter notebook, using rpy2, and am getting an error, pasted below. As can be seen, previous package importation works okay, but for some reason afex does not work. Does anyone know how to troubleshoot this?

FYI: This is done through anaconda's jupyter notebook on a Mac, using rpy2 version: 2.9.1 and R version: ('3', '4.3', '', 73796).

`#Importing key libraries from python.

import numpy as np
import pandas as pd
import seaborn as sns
import scipy.stats as stats
import matplotlib.lines as mlines
from matplotlib import pyplot as plt
from statsmodels.formula.api import ols

Import rpy2 and get version info.

import rpy2

Importing key rpy2 top-level package for interfacing python with R.

import rpy2.robjects as robjects

from rpy2.robjects.packages import importr

Importing r specific package as python objects

import R's "base" package

base = importr('base')

import R's "utils" package

utils = importr('utils')

inport R's "afex" package

afex = importr('afex')

/anaconda3/lib/python3.6/site-packages/rpy2/rinterface/init.py:145: RRuntimeWarning: Error in loadNamespace(name) : there is no package called ‘afex’

warnings.warn(x, RRuntimeWarning)
/anaconda3/lib/python3.6/site-packages/rpy2/rinterface/init.py:145: RRuntimeWarning: In addition:
warnings.warn(x, RRuntimeWarning)
/anaconda3/lib/python3.6/site-packages/rpy2/rinterface/init.py:145: RRuntimeWarning: There were 50 or more warnings (use warnings() to see the first 50)
warnings.warn(x, RRuntimeWarning)
/anaconda3/lib/python3.6/site-packages/rpy2/rinterface/init.py:145: RRuntimeWarning:

warnings.warn(x, RRuntimeWarning)


RRuntimeError Traceback (most recent call last)
in ()
13
14 # inport R's "afex" package
---> 15 afex = importr('afex')

/anaconda3/lib/python3.6/site-packages/rpy2/robjects/packages.py in importr(name, lib_loc, robject_translations, signature_translation, suppress_messages, on_conflict, symbol_r2python, symbol_check_after, data)
451 if _package_has_namespace(rname,
452 _system_file(package = rname)):
--> 453 env = _get_namespace(rname)
454 version = _get_namespace_version(rname)[0]
455 exported_names = set(_get_namespace_exports(rname))

RRuntimeError: Error in loadNamespace(name) : there is no package called ‘afex’
`

Thanks,
rkd1

don't overwrite global (g)lmer() function

Hi there,

Recent behavior in afex seems to have changed. I need my lmer models to be class lme4:lmer (stargazer, for example, chokes on lmerTest::lmer objects). However, when i set afex_options(lmer_function = "lme4"), mixed() fails. Rewriting my code to use lme4::lmer instead of just lmer is pretty ugly. Would it be possible to allow options to be separately set for the global lmer function and the lmer afex uses internally separately? If there's a better solution, I'm all ears...

Thanks for the nice package, by the way.

Allie

aov_ error for repeated-measures designs: replacement has 0 rows, data has 4

Error for aov_ functions with repeated-measures designs

  • afex: 0.18-0
  • R: 3.5.0
  • OS: Ubuntu 18.04 bionic

When I attempt a standard repeated-measures analysis using any of the aov_ functions I get a cryptic error message.

library(afex)

# use tooth growth data but add a spurious ID variable to imitate within-subjects design
d = ToothGrowth
d$ID = factor(rep(1:10,6))
d$dose = factor(d$dose)

# confirm that standard aov() works
aov(len ~ supp*dose + Error(ID/(supp*dose)), d)

# all of the following result in the same error
aov_ez(dv='len',between=c('supp','dose'),within=c('supp','dose'),id='ID',data=d)
aov_car(len ~ supp*dose + Error(ID/(supp*dose)), d)
aov_4(len ~ supp*dose + ((supp*dose)|ID), d)

The error:

Error in `$<-.data.frame`(`*tmp*`, "ges", value = numeric(0)) : 
  replacement has 0 rows, data has 4

Session Info:

R version 3.5.0 (2018-04-23)
Platform: x86_64-pc-linux-gnu (64-bit)
Running under: Ubuntu 18.04 LTS

Matrix products: default
BLAS: /usr/lib/x86_64-linux-gnu/openblas/libblas.so.3
LAPACK: /usr/lib/x86_64-linux-gnu/libopenblasp-r0.2.20.so

locale:
 [1] LC_CTYPE=en_US.UTF-8       LC_NUMERIC=C               LC_TIME=en_US.UTF-8       
 [4] LC_COLLATE=en_US.UTF-8     LC_MONETARY=en_US.UTF-8    LC_MESSAGES=en_US.UTF-8   
 [7] LC_PAPER=en_US.UTF-8       LC_NAME=C                  LC_ADDRESS=C              
[10] LC_TELEPHONE=C             LC_MEASUREMENT=en_US.UTF-8 LC_IDENTIFICATION=C       

attached base packages:
[1] stats     graphics  grDevices utils     datasets  methods   base     

other attached packages:
[1] afex_0.18-0     lsmeans_2.27-62 lme4_1.1-17     Matrix_1.2-14  

loaded via a namespace (and not attached):
 [1] Rcpp_0.12.17        mvtnorm_1.0-8       lattice_0.20-35     zoo_1.8-2          
 [5] digest_0.6.15       cellranger_1.1.0    plyr_1.8.4          backports_1.1.2    
 [9] acepack_1.4.1       stats4_3.5.0        coda_0.19-1         ggplot2_2.2.1      
[13] pillar_1.2.3        rlang_0.2.1         lazyeval_0.2.1      curl_3.1           
[17] multcomp_1.4-8      readxl_1.1.0        rstudioapi_0.7      minqa_1.2.4        
[21] data.table_1.11.4   car_3.0-0           nloptr_1.0.4        rpart_4.1-13       
[25] checkmate_1.8.5     splines_3.5.0       stringr_1.3.1       foreign_0.8-70     
[29] htmlwidgets_1.2     munsell_0.5.0       compiler_3.5.0      pkgconfig_2.0.1    
[33] base64enc_0.1-3     lmerTest_2.0-36     htmltools_0.3.6     nnet_7.3-12        
[37] tibble_1.4.2        gridExtra_2.3       htmlTable_1.12      coin_1.2-2         
[41] Hmisc_4.1-1         rio_0.5.10          codetools_0.2-15    MASS_7.3-50        
[45] grid_3.5.0          nlme_3.1-137        xtable_1.8-2        gtable_0.2.0       
[49] magrittr_1.5        scales_0.5.0        zip_1.0.0           stringi_1.2.3      
[53] estimability_1.3    carData_3.0-1       reshape2_1.4.3      latticeExtra_0.6-28
[57] sandwich_2.4-0      openxlsx_4.1.0      Formula_1.2-3       TH.data_1.0-8      
[61] RColorBrewer_1.1-2  tools_3.5.0         forcats_0.3.0       hms_0.4.2          
[65] parallel_3.5.0      abind_1.4-5         survival_2.42-4     colorspace_1.3-2   
[69] cluster_2.0.7-1     knitr_1.20          haven_1.1.2         modeltools_0.2-21  

Afex or car ANOVA models vs lme4?. Observed variables

Hello.

I don't know if this is the proper place to ask this
just in case, I've also posted my question here

https://stackoverflow.com/questions/37102075/how-to-convert-afex-or-car-anova-models-to-lmer-observed-variables

but nobody replies.

In the afex package we can find this example of ANOVA analysis:
data(obk.long, package = "afex")

estimate mixed ANOVA on the full design:

can be written in any of these ways:

aov_car(value ~ treatment * gender + Error(id/(phase*hour)), data = obk.long,
        observed = "gender")

aov_4(value ~ treatment * gender + (phase*hour|id), data = obk.long,
        observed = "gender")

aov_ez("id", "value", obk.long, between = c("treatment", "gender"), 
       within = c("phase", "hour"), observed = "gender")

My question is, How can I write the same model in lme4? In particular, I don't know how to include the "observed" term?

If I just write

lmer(value ~ treatment * gender + (phase*hour|id), data = obk.long,
     observed = "gender")

I get an error telling that observed is not a valid option.

Furthermore, if I just remove the observed option lmer produces the error:
Error: number of observations (=240) <= number of random effects (=240) for term (phase * hour | id); the random-effects parameters and the residual variance (or scale parameter) are probably unidentifiable.

Where in the lmer syntax do I specify the "between" or "within" variable?. As far as I know you just write the dependent variable on the left side and all other variables on the right side, and the error term as (1|id).

The package "car" uses the idata for the intra-subject variable.

C_stri_join' not found

When I run any aov_ez() or aov_car(), even the examples from the help, I get this error:

Error in stri_c(..., sep = sep, collapse = collapse, ignore_null = TRUE) :
object 'C_stri_join' not found

I've tried reinstalling stringi and stringr packages, but it doesn't fix the problem.

Regards

aov_car error?

Hello.

When I run the examples aov_ez works, but aov_car always produces this error:

Error in [.data.frame(data, , id) : undefined columns selected

set_data_arg option throwing (unnecessary) warning

When running mixed (afex 0.19.1) the option set_data_arg throws a warning despite working as intended.

data(obk.long)
m <- mixed(value ~ treatment + (1|id), obk.long, set_data_arg = TRUE)
Contrasts set to contr.sum for the following variables: treatment, id
Fitting one lmer() model. [DONE]
Calculating p-values. [DONE]
Warning messages:
1: extra argument(s) ‘set_data_arg’ disregarded 
2: extra argument(s) ‘set_data_arg’ disregarded
> m$full_model@call
lme4::lmer(formula = value ~ treatment + (1 | id), data = obk.long, 
    set_data_arg = TRUE)

> m <- mixed(value ~ treatment + (1|id), obk.long, set_data_arg = FALSE)
Contrasts set to contr.sum for the following variables: treatment, id
Fitting one lmer() model. [DONE]
Calculating p-values. [DONE]
Warning messages:
1: extra argument(s) ‘set_data_arg’ disregarded 
2: extra argument(s) ‘set_data_arg’ disregarded 
> m$full_model@call
lme4::lmer(formula = value ~ treatment + (1 | id), data = data, 
    set_data_arg = FALSE)

Also I'm somewhat confused about the way this works inside a function. It appears to do the opposite of what I expect, by only working with emmeans when set to FALSE?


f <- function(dat, set_data_arg) {
  m <- mixed(value ~ treatment + (1|id), dat, set_data_arg = set_data_arg)
  emmeans(m, "treatment")  
}

> f(obk.long, TRUE)
Contrasts set to contr.sum for the following variables: treatment, id
Fitting one lmer() model. [DONE]
Calculating p-values. [DONE]
Error in is.data.frame(data) : object 'dat' not found
In addition: Warning messages:
1: extra argument(s) ‘set_data_arg’ disregarded 
2: extra argument(s) ‘set_data_arg’ disregarded 
 Error in ref_grid(object, ...) : 
  Perhaps a 'data' or 'params' argument is needed 

> f(obk.long, FALSE)
Contrasts set to contr.sum for the following variables: treatment, id
Fitting one lmer() model. [DONE]
Calculating p-values. [DONE]
 treatment emmean        SE df lower.CL upper.CL
 control     4.20 0.6536551 13 2.787864 5.612136
 A           6.25 0.7308086 13 4.671184 7.828816
 B           6.00 0.5524394 13 4.806527 7.193473

Degrees-of-freedom method: kenward-roger 
Confidence level used: 0.95 
Warning messages:
1: extra argument(s) ‘set_data_arg’ disregarded 
2: extra argument(s) ‘set_data_arg’ disregarded

Consistency of syntax between lmer and aov_4

Am I wrong to think that these two models should do the same thing (or at least, be a close approximation of one another)?

library(lmerTest)
library(afex)
aov_4(distance ~ age + (1|Subject), data=nlme::Orthodont, print.formula = T)
anova(lmer(distance ~ factor(age) + (1|Subject), data=nlme::Orthodont))

In practice this aov_4 call doesn't work because it doesn't properly specify the nesting of multiple observations within Subject. To get (what I think is) the equivalent of the lmer model you need to write:

aov_4(distance ~ age + (age|Subject), data=nlme::Orthodont)

I was hoping to be use aov_4 to help students transition between RM Anova and mixed models, but I'm worried these subtle differences in syntax will make it even more confusing than simply using aov_ez.

Documentation glitch for afex_aov methods

Henrik,

I notice that the help page for afex_aov methods includes the text:

recover_data and emm_basis
Provide the backbone for using emmeans and related functions from emmeans directly on afex_aov objects by returning a ref.grid object. Should not be called directly but through the functionality provided by emmeans.

You should replace ref.grid here with emmGrid (and also replace its link). Not a big issue but worth correcting before your next update.

Cheers,

Russ

Error in retrieving help of `aov_*` in RStudio

When typing aov_ in RStudio the following window pops up, suggesting there is an error in help document.

image

Error messages:

Error in substring(html, match + 6, match + attr(match, "match.length") -  : 
  invalid multibyte string at '<98>*<2a>*鈥<99> 0.001 鈥<98>**鈥<99> 0.01 鈥<98>*鈥<99> 0.05 鈥<98>+鈥<99> 0.1 鈥<98> 鈥<99> 1

# "numeric" variables are per default converted to factors (as long as factorize = TRUE):
obk.long$hour2 &lt;- as.numeric(as.character(obk.long$hour))

# gives same results as calls before
aov_car(value ~ treatment * gender + Error(id/phase*hour2), 
        data = obk.long, observed = c("gender"))


# ANCOVA: adding a covariate (necessary to set factorize = FALSE)
aov_car(value ~ treatment * gender + age + Error(id/(phase*hour)), 
        data = obk.long, observed = c("gender", "age"), factorize = FALSE)

aov_4(value ~ treatment * gender + age + (phase*hour|id), 
        data = obk.long, observed = c("gender", "age"), factorize = FALSE)

aov_ez("id", "value", obk.long, between = c("treatment", "gender"), 
        within = c("phase", "hour"), covariate = "age", 
        observed = c("gender", "age"), factorize = FALSE)


# aggregating over one within-su

Session Information:

sessioninfo::session_info()
#> - Session info ----------------------------------------------------------
#>  setting  value                         
#>  version  R version 3.5.3 (2019-03-11)  
#>  os       Windows 10 x64                
#>  system   x86_64, mingw32               
#>  ui       RTerm                         
#>  language (EN)                          
#>  collate  Chinese (Simplified)_China.936
#>  ctype    Chinese (Simplified)_China.936
#>  tz       Asia/Taipei                   
#>  date     2019-04-08                    
#> 
#> - Packages --------------------------------------------------------------
#>  package     * version date       lib source        
#>  assertthat    0.2.1   2019-03-21 [1] CRAN (R 3.5.3)
#>  cli           1.1.0   2019-03-19 [1] CRAN (R 3.5.3)
#>  crayon        1.3.4   2017-09-16 [1] CRAN (R 3.5.0)
#>  digest        0.6.18  2018-10-10 [1] CRAN (R 3.5.1)
#>  evaluate      0.13    2019-02-12 [1] CRAN (R 3.5.2)
#>  highr         0.8     2019-03-20 [1] CRAN (R 3.5.3)
#>  htmltools     0.3.6   2017-04-28 [1] CRAN (R 3.5.0)
#>  knitr         1.22    2019-03-08 [1] CRAN (R 3.5.3)
#>  magrittr      1.5     2014-11-22 [1] CRAN (R 3.5.0)
#>  Rcpp          1.0.1   2019-03-17 [1] CRAN (R 3.5.3)
#>  rmarkdown     1.12    2019-03-14 [1] CRAN (R 3.5.2)
#>  sessioninfo   1.1.1   2018-11-05 [1] CRAN (R 3.5.1)
#>  stringi       1.4.3   2019-03-12 [1] CRAN (R 3.5.2)
#>  stringr       1.4.0   2019-02-10 [1] CRAN (R 3.5.2)
#>  withr         2.1.2   2018-03-15 [1] CRAN (R 3.5.0)
#>  xfun          0.6     2019-04-02 [1] CRAN (R 3.5.3)
#>  yaml          2.2.0   2018-07-25 [1] CRAN (R 3.5.1)
#> 
#> [1] C:/Users/liang/Documents/R/win-library/3.5
#> [2] C:/Program Files/R/R-3.5.3/library

Created on 2019-04-08 by the reprex package (v0.2.1)

Using afex for simple one-way ANOVA

I was hoping to use afex for all my ANOVAing needs, since it's a little easier if I can tell students to just use the afex functions and then the output will match the SPSS results presented in the course I'm tutoring for.

However, unless I misunderstood yet another thing and that's not possible by design, a basic attempt fails:

load(url("https://qm.jemu.name/data/ngo")) # The possibly infamous Kähler dataset

# A tibble: 6 × 2
  jahrgang deutsch
     <ord>   <int>
1       11       4
2       11       4
3       11       8
4       11       6
5       11       8
6       11       6

aov_car(deutsch ~ jahrgang, data = ngo)

Error in if (make.names(name) != name) { : 
  missing value where TRUE/FALSE needed

Wheras

aov(deutsch ~ jahrgang * geschl, data = ngo)

works just fine.
Attempting to use aov_ez of course did not work, as I do not have an id variable in this case, which is a mandatory argument in that function, leading me to assume that afex is only meant to work with repeated measure designs or other designs more complex than what I'm used to.

My primary motivation is just to reproduce SPSS results reliably, and give student's an easy way to switch ANOVA types.

That is also the motiviation between tadaatoolbox::tadaa_aov(), but I apparently just pumping models through car::Anova(…, type = 3) etc. is not sufficient – but I digress.

TL;DR:

Is a simple one-way ANOVA not possible using afex?

Differences in output between `lmer` and `mixed`

I've noticed that when specifying a model using the lmer function in the lme4 package which contains factor-type predictors, the suffix indicating the level of the predictor is a character string of that factor level, as is the case for treatment here:

library(afex)

data(obk.long)

m1 <- lmer(value ~ treatment + (1|id), obk.long)
summary(m1)

Fixed effects:
        Estimate Std. Error t value
(Intercept)    4.200      0.654    6.43
treatmentA     2.050      0.980    2.09
treatmentB     1.800      0.856    2.10

However, when using the mixed function in the afex package, the suffix is numeric:

m2 <- mixed(value ~ treatment + (1|id), obk.long)
summary(m2$full.model) # this should be the same as the lmer output... it's er, not

Fixed effects:
            Estimate Std. Error t value
(Intercept)    5.483      0.375   14.62
treatment1    -1.283      0.532   -2.41
treatment2     0.767      0.565    1.36

Firstly, could you comment on what causes the difference in the predictor label level suffix? Secondly, what's up with the differences in the fixed effects?

Effect size from post-hoc tests

Hello!

Is there any way to calculate generalised eta-squared for contrasts run on afex anova's using the lsmeans/multcomp procedures detailed in your post-hoc tests vignette?

Cheers

all_fit nmkbw does not work, when afex is not attached

I intend to fix later.

library("lme4")
library("optimx")
gm1 <- glmer(cbind(incidence, size - incidence) ~ period + (1 | herd),
             data = cbpp, family = binomial)

gm_all <- afex::all_fit(gm1)
!sapply(gm_all,inherits,"error") 
#                       bobyqa.                  Nelder_Mead. 
#                          TRUE                          TRUE 
#                 optimx.nlminb               optimx.L-BFGS-B 
#                          TRUE                          TRUE 
# nloptwrap.NLOPT_LN_NELDERMEAD     nloptwrap.NLOPT_LN_BOBYQA 
#                          TRUE                          TRUE 
#                        nmkbw. 
#                         FALSE 

gm_all[["nmkbw."]]
## <simpleError in getOptfun(optimizer): couldn't find optimizer function nmkbw>

library("afex")
gm_all <- all_fit(gm1)
!sapply(gm_all,inherits,"error") 
#                       bobyqa.                  Nelder_Mead. 
#                          TRUE                          TRUE 
#                 optimx.nlminb               optimx.L-BFGS-B 
#                          TRUE                          TRUE 
# nloptwrap.NLOPT_LN_NELDERMEAD     nloptwrap.NLOPT_LN_BOBYQA 
#                          TRUE                          TRUE 
#                        nmkbw. 
#                          TRUE 

Mixed function not working for GLMM

Hello,

I am trying to run a GLMM (Inverse gaussian with inverse link function) using the mixed function. According to the documentation, I can use LRT and PB for the method argument. However, both of these give errors, as below.

PB error

Screen Shot 2019-09-13 at 4 25 22 pm

LRT error

Screen Shot 2019-09-13 at 4 41 00 pm

Any insight would be greatly appreciated :)

Significance asterisks

Significance asterisks should appear after the p-value, not the F-value. What afex produces looks like this:

Response: SpecLen
         Effect      df  MSE       F ges p.value
1        BlockF   4, 16 6.51 7.35 ** .27    .001
2        TrialF   9, 36 0.67    1.19 .01     .33
3 BlockF:TrialF 36, 144 0.90    1.35 .08     .11

but in order to maintain consistency with pretty much every other R table, it really should look like this:

Response: SpecLen
         Effect      df  MSE       F ges p.value
1        BlockF   4, 16 6.51    7.35 .27    .001 **
2        TrialF   9, 36 0.67    1.19 .01     .33
3 BlockF:TrialF 36, 144 0.90    1.35 .08     .11

Avoid data.table dependency?

There is a major bug with the data.table, preventing it from loading in R 3.5+ on Windows. See more here.

Unfortunately, afex will not load without the data.table library. So Afex is dead on Windows for now.

> library(afex)
Error: package or namespace load failed for ‘afex’ in loadNamespace(j <- i[[1L]], c(lib.loc, .libPaths()), versionCheck = vI[[j]]):
 there is no package called ‘data.table’

Is there any possibility of removing the data.table dependency from afex?

Add `sphericity()` function/method

afex_aov objects should have a method that returns the test of sphericity for within-subject ANOVAs. This would allow the following coding style (which some might like):

library("afex")
data(obk.long, package = "afex")

# estimate mixed ANOVA on the full design:
a1 <- aov_car(value ~ treatment * gender + Error(id/(phase*hour)), 
        data = obk.long, observed = "gender")
sphericity(a1)
nice(a1, correction = "HF")

Maybe something similar for Levene tests would be nice as well (e.g., based on leveneTest() in car).

Both ideas are based on discussions with Charlotte Tate.

`afex_plot` not fully compatible with glmm

When fitting a glmm model (either with lme4::glmer or with afex::mixed), I've found that I cannot use afex_plot to plot the following:

  • Original data is not plotted (I suspect due to the link-transformed scale?)
  • When trying to plot the response scale (by passing emmeans_arg = list(type = "response")), an error is produced.
> library(afex)
> library(mlmRev)
>
> gm1 <- mixed(use ~ age + I(age^2) + urban + livch + (1 | district), method = 'LRT',
+              family = binomial, data = Contraception)
>
> afex_plot(gm1,~age,emmeans_arg = list(type = "response"),data_plot = TRUE)
Aggregating data over: district
Error in FUN(X[[i]], ...) : object 'y' not found
In addition: There were 50 or more warnings (use warnings() to see the first 50)

I suspect that I am pushing afex_plot to its limit, perhaps beyond its intended use.

Thanks!

Transition from lsmeans to emmeans

hi henrik,

i sat down the other day to begin looking into what it would take to transition afex from lsmeans to emmeans, but then i noticed the emmeans branch! anyhow, i'm creating this issue so i (and others) can track your progress :)

we'll transition jmv over to emmeans once afex is ready.

let me know if you need any assistance with anything.

with thanks

add residuals function for afex_aov objects

afex_aov objects should have a residuals function that works for both between and within models. The following code could be the starting point:

library("afex")
data(md_12.1)
a1 <- aov_ez("id", "rt", md_12.1, within = c("angle", "noise"))

residuals.afex_aov <- function(object, ...) {
  if (length(attr(object, "within")) > 0) {
    str(object, 1)
    dw <- object$data$wide
    dw[,-1] <- residuals(object$lm)
    NULL # [...]
  } else {
    return(residuals(object$lm))
  }
}

md_12.1$residuals <- residuals(a1)

Why aov_ez default output GG corrected results?

Why aov_ez default output GG corrected results even while Mauchly Tests for Sphericity is not significant? Is that appropriate?

Is there an easy manner to extract the Mauchly Tests p-value from afex_aov objects? I want to set correction method based on that. Or is it possible to provided an Auto correct option besides GG and HF based this:

image

mixed/lmer_alt do not work with splines in formula

library("afex")
library("splines")

summary(lmer(Reaction ~ ns(Days, df = 3) + (ns(Days, df = 3) || Subject),
                    data = sleepstudy))$varcor
## Groups    Name              Std.Dev. Corr       
## Subject   (Intercept)       24.616              
## Subject.1 ns(Days, df = 3)1 56.662              
##           ns(Days, df = 3)2 64.683   0.566      
##           ns(Days, df = 3)3 47.919   0.435 0.717
## Residual                    21.024     

summary(lmer_alt(Reaction ~ ns(Days, df = 3) + (ns(Days, df = 3) || Subject),
                    data = sleepstudy))$varcor
## Numerical variables NOT centered on 0 (i.e., interpretation of all main effects might be difficult if in interactions): Days
## Error in parse(text = x, keep.source = FALSE) : 
##   <text>:1:50: unexpected numeric constant
## 1: Reaction~ns(Days, df = 3)+(1+re1.ns(Days, df = 3)1
##                                                      ^

Example taken from R-sig-mixed: https://stat.ethz.ch/pipermail/r-sig-mixed-models/2017q4/026226.html

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.