# Transitioning to emmeans from lsmeans

#### Russ Lenth

#### 2018-03-31

## Overview

emmeans is a continuation of the lsmeans package. The name is changed for two reasons:

1. The term “least-squares means” is misleading in terms of describing the analyses it provides. The term “estimated marginal means” (EMMs) is well-accepted, and it better describes the basic idea that we use marginal means of predictions over a reference grid. When we do that with, say, an ordinal model, the concept “estimated marginal mean” makes sense while “least-squares mean” does not, because no least-squares methods are used to fit the model or obtain the EMMs.
2. A number of changes are made to the internal architecture of the package. The lsmeans package had two classes, `ref.grid` and `lsmobj`, and it was confusing to some users that they needed to use primarily `ref.grid` methods to summarize `lsmobj` objects. The emmeans package has only an `emmGrid` class that covers both of the old classes. Changing the name of the package at the same time as the object classes are changed makes for a cleaner transition.

## User impact

For the most part, all that most users need to do to transition from using the lsmeans package is to use `require(emmeans)` or `library(emmeans)` to load the package. With that one change, almost all of the code in the using-lsmeans vignette runs without alteration, and almost all examples from the help system for lsmeans also work as-is. Even though we now emphasize using the `emmeans()` function and related “em” functions, `lsmeans()` and its relatives are still available as wrappers for the new functions.

That said, here are a few changes that former lsmeans users may need to be aware of:

- The package provides a utility `emmeans:::convert_scripts()` that may be used to convert old scripts that used lsmeans to use emmeans instead. See more below

- Some functions are deprecated, e.g. `ref.grid()`, `lsm.options()`, etc. They will work, but you will get a deprecated message advising you to use `ref_grid()` and `emm_options()`, etc.1

- While the functions `lsmeans()`, `lsmip()`, etc. will continue to be provided, all the help-page and vignette descriptions refer to their new counterparts `emmeans()`, `emmip()`, etc. So you will need to get accustomed to new terminology like “EMMs”, even if you don’t choose to use it in your own work.2

- If you have any scripts that include calls prefixed by `lsmeans::`, or calls to `require(lsmeans)` or `library(lsmeans)`, obviously you need to change these to use `emmeans` instead.
- If you have any custom contrast functions, you need to rename them with an extension of `.emmc` instead of `lsmc`. See the example under `help("contrast-methods")`.
- If you have saved results from previous runs in lsmeans (i.e., `ref.grid` or `lsmobj` objects), they should still work in emmeans. The issue you may face, though, is that the lsmeans package could get loaded simply because these objects are present, and put in the `search()` path. To make sure you’re using the new package, convert the objects to class `emmGrid` – e.g., `my_new_ref_grid <- as.emmGrid(my.old.ref.grid)`. Running the non-exported function `emmeans:::convert_workspace()` may be used to convert all the objects in an environment (the global one by default) and clean out any dependencies on lsmeans. See more below
- The `emmip()` and `plot()` functions use graphics from the ggplot2 package by default. If you prefer the lattice graphics produced by the lsmeans package, they are still available: Use `emm_options(graphics.engine = "lattice")` to change the default, or add `engine = "lattice"` to the call to for a particular plot.
- To get complete information about models supported by emmeans, use `vignette("models")` rather than the help page of the same name. It includes a quick reference chart at the beginning that should prove helpful.
- The “using-lsmeans” vignette has been replaced by a number of smaller vignettes that cover specific topics. Start with `vignette("basics")` to obtain an overview. The vignette index has links to all the vignettes.
- The options `lsmeans` and `ref.grid` have been remapped to `emmeans` and `ref_grid` respectively. For example, calling `lsm.options(lsmeans = ...)` remaps as `emm_options(emmeans = ...)`. See `help("emm_options", package = "emmeans")` and `help("lsm.options", package = "lsmeans")` for explanations of these options.

- The degrees-of-freedom saga, continued… Initially, lsmeans used the pbkrtest package to compute degrees of freedom (via the Kenward-Roger method) for `lme4::lmerMod` models. Later, the default was changed to the Satterthwaite method, implemented in the lmerTest package. Both methods are problematic; but I have decided to revert to the Kenward-Roger method as the system default. The default may be changed via `emm_options(lmer.df = ...)`. See `vignette("models")` for details.

## Converting scripts

The user may run

    emmeans:::convert_scripts()

to convert R scripts or R Markdown files to use emmeans functions. (This is a non-exported function – you need three `:`s in there.)

- You will get a file-open dialog where you can browse for the files – multiple files may be selected.
- You will also be prompted for whether or not you want calls to `lsmeans()` or `pmmeans()`to be replaced by calls to `emmeans()` (it’s your choice; the former still work).
- Each converted file is saved in the same directory with `-emm` added to the root name; for example, `myfile.R` is converted and saved as `myfile-emm.R`.

The conversion routines will convert the following to their `emmeans` counterparts:

- `require(lsmeans)` and `library(lsmeans)` to `require(emmeans)` and `library(emmeans)`
- `lsmeans::` to `emmeans::`
- `ref.grid(` to `ref_grid(`
- `lsm.options(` and `get.lsm.option(` to `emm_options(` and `get_emm_option(` (arguments thereof are also converted).
- `.lsmc` to `.emmc` (contrast-method names)
- `lsmeans(` and relatives to `emmeans(` and relatives, if opted for
- `pmmeans(` and relatives to `emmeans(` and relatives, if opted for

## Converting workspaces

If you have any objects from the lsmeans package laying around, it is all too likely that the lsmeans package will be loaded, and perhaps even get added to the search path. This can create annoying messages, if not conflicts. When this happens, type

    emmeans:::convert_workspace()

on the console. This will convert any `ref.grid` or `lsmobj` objects laying around to the new `emmGrid` class, and unload all vestiges of lsmeans.

Once you are comfortable using emmeans in place of lsmeans, you may effect a permanent solution (the “nuclear option?”) by uninstalling the lsmeans package. Doing so will not prevent you from converting old workspaces or scripts. Watch your package updates carefully, though, as it may get re-installed if it is still imported by another package.

## Notes for package developers to transition to emmeans support

if you are the developer of a package that supports lsmeans, and you want to transition to supporting emmeans, I make the following suggestions:

1. Currently, your package provides methods `recover.data.xyz()` and `lsm.basis.xyz()`, where `xyz` stands in for the class of your object. Rename these functions `recover_data.xyz()` and `emm_basis.xyz()`.
2. Any calls to `lsmeans::` functions in the above methods should be changed to the corresponding `emmeans::` functions.
3. For a period of time, you may want to continue support for lsmeans as well. So write new functions `recover.data.xyz()` and `lsm.basis.xyz()` that just call their counterparts.
4. In your `DESCRIPTION` file, add `emmeans` to `Imports`, and make sure that `lsmeans` is not in `Imports`.
5. In your `NAMESPACE` file,
   1. add `importFrom(emmeans, recover_data, emm_basis)`
   2. add `S3method(recover_data, xyz)`
   3. add `S3method(emm_basis, xyz)`
   4. add `export(recover.data.xyz, lsm.basis.xyz)`. That is, export them as functions, and not as S3 methods
   5. In lieu of (a)-(c) above, you could just export the functions `recover_data.xyz` and `emm_basis.xyz`.

1. Many of the deprecated functions, like `ref.grid()`, are renamed to avoid possible confusion in S3 method dispatch: how do we know that `summary.ref.grid()` wasn’t a `summary.ref()` method for class `grid`, rather than a `summary()` method for class `ref.grid`?↩

2. By the way, the `pmmeans()`, `pmmip()`, etc. wrappers already provided in lsmeans are also still available.↩