Reputation: 1932
I am trying to make a function that fits a mixed model on the chosen variable.
If I run this command inside the function:
lme4::lmer(VAR ~ cVAR + (1|ID), data=df)
I get the error:
Error in model.frame.default(data = df, drop.unused.levels = TRUE, formula = VAR ~ :
variable lengths differ (found for 'ID')
I have tested my code in several ways, and I just cant find out whats wrong. I can make plots from inside the function without problems. If I try to just print the dataframe used inside the function it looks exactly as I want it to look. Furthermore - If I run the lmer command outside the function (substituting VAR and cVAR for X and cX), the command runs without problems.
I therefore believe the error is caused by running lmer() inside the function. This Question has a similar problem, but is having a different error message than me.
Is there any way to run lmer inside a function without getting the error?
Reproducible example:
set.seed(1)
org <- data.frame(
X = rep(1:10+rnorm(10,mean=1,sd=0.5),2),
cX = rep(1:10+rnorm(10,mean=1,sd=0.5),2),
Y = rep(1:10+rnorm(10,mean=1,sd=0.5), 2),
cY = rep(1:10-rnorm(10,mean=1,sd=0.5),2),
Frame = rep(1:5, 4),
JN = rep(1:2, each=5),
ID = rep(1:2, each=10))
FUNC <- function(VAR) {
VAR <- deparse(substitute(VAR))
cVAR <- paste0("c", VAR)
df <- dplyr::select(org, ID, JN, Frame, VAR, cVAR) # Keeping only a subset of the data
df <- df %>% tidyr::drop_na() #Keeping only complete cases
stopifnot(all(c(VAR, cVAR) %in% names(df)))
MixedModel <- lme4::lmer(VAR ~ cVAR + (1|ID), data=df)
b <- plot(MixedModel)
}
#It works fine outside the function:
MixedModel_no_FUNC <- lme4::lmer(X ~ cX + (1|ID), data=org)
plot(MixedModel_no_FUNC)
#But not inside the function
FUNC(X)
My sessionInfo in case it is relevant
R version 3.4.1 (2017-06-30)
Platform: x86_64-w64-mingw32/x64 (64-bit)
Running under: Windows 7 x64 (build 7601) Service Pack 1
Matrix products: default
locale:
[1] LC_COLLATE=Danish_Denmark.1252 LC_CTYPE=Danish_Denmark.1252
[3] LC_MONETARY=Danish_Denmark.1252 LC_NUMERIC=C
[5] LC_TIME=Danish_Denmark.1252
attached base packages:
[1] stats graphics grDevices utils datasets methods base
other attached packages:
[1] lme4_1.1-14 Matrix_1.2-10 ggExtra_0.7 BlandAltmanLeh_0.3.1
[5] gganimate_0.1.0.9000 gridExtra_2.3 bindrcpp_0.2 dplyr_0.7.3
[9] purrr_0.2.3 readr_1.1.1 tidyr_0.7.1 tibble_1.3.4
[13] tidyverse_1.1.1 ggmap_2.7 ggplot2_2.2.1
loaded via a namespace (and not attached):
[1] Rcpp_0.12.13 lubridate_1.6.0 lattice_0.20-35 png_0.1-7 assertthat_0.2.0
[6] digest_0.6.12 psych_1.7.8 mime_0.5 R6_2.2.2 cellranger_1.1.0
[11] plyr_1.8.4 httr_1.3.1 RgoogleMaps_1.4.1 rlang_0.1.2 lazyeval_0.2.0
[16] readxl_1.0.0 minqa_1.2.4 geosphere_1.5-7 miniUI_0.1.1 nloptr_1.0.4
[21] splines_3.4.1 proto_1.0.0 labeling_0.3 stringr_1.2.0 foreign_0.8-69
[26] munsell_0.4.3 shiny_1.0.5 broom_0.4.2 compiler_3.4.1 httpuv_1.3.5
[31] modelr_0.1.1 pkgconfig_2.0.1 mnormt_1.5-5 htmltools_0.3.6 tidyselect_0.2.1
[36] MASS_7.3-47 bitops_1.0-6 grid_3.4.1 nlme_3.1-131 jsonlite_1.5
[41] xtable_1.8-2 gtable_0.2.0 magrittr_1.5 scales_0.5.0 stringi_1.1.5
[46] mapproj_1.2-5 reshape2_1.4.2 sp_1.2-5 xml2_1.1.1 rjson_0.2.15
[51] tools_3.4.1 forcats_0.2.0 glue_1.1.1 maps_3.2.0 hms_0.3
[56] jpeg_0.1-8 parallel_3.4.1 yaml_2.1.14 colorspace_1.3-2 rvest_0.3.2
[61] knitr_1.17 bindr_0.1 haven_1.1.0
Upvotes: 0
Views: 284
Reputation: 1234
You have some conflicting names of objects in your dataframe and the environment in your function. Here's your data:
org <- data.frame(
X = rep(1:10+rnorm(10,mean=1,sd=0.5),2),
cX = rep(1:10+rnorm(10,mean=1,sd=0.5),2),
Y = rep(1:10+rnorm(10,mean=1,sd=0.5), 2),
cY = rep(1:10-rnorm(10,mean=1,sd=0.5),2),
Frame = rep(1:5, 4),
JN = rep(1:2, each=5),
ID = rep(1:2, each=10))
I choose to just pass a string to the VAR argument instead of deparsing like you did. Then check if VAR and cVAR are in the dataframe. Then I reduce the dataframe and rename VAR and cVAR to Y and X so that when you call lmer() you're sure that the formula is referring to the variables in the data.frame and not the objects in the function environment.
library(lme4)
FUNC <- function(VAR = "VAR", df) {
cVAR <- paste0("c", VAR)
stopifnot(all(c(VAR, cVAR) %in% names(df)))
df <- df[,c("ID", "JN", "Frame", VAR, cVAR)]
names(df) <- c(c("ID", "JN", "Frame", "Y", "X"))
df <- df[complete.cases(df),]
MixedModel <- lme4::lmer(Y ~ X + (1|ID), data=df)
plot(MixedModel)
}
FUNC(VAR = "X", df = org)
Upvotes: 1