Join GitHub today
GitHub is home to over 28 million developers working together to host and review code, manage projects, and build software together.
Sign upFunction margins not functional with lapply? #94
Comments
leeper
added
bug
question
and removed
bug
labels
May 11, 2018
This comment has been minimized.
Show comment
Hide comment
This comment has been minimized.
leeper
May 11, 2018
Owner
Install the latest version from GitHub and you should be able to mapply()
. The issue is that you need to pass a data
argument because margins()
can't tell what the source data are in this context. Here's an example:
> (lstMargins <- mapply(margins, model = lstFits, data = lstData, SIMPLIFY = FALSE))
$`3`
Average marginal effects
lm(formula = mpg ~ cyl + wt, data = x)
cyl wt
-0.838 -2.473
$`4`
Average marginal effects
lm(formula = mpg ~ cyl + wt, data = x)
cyl wt
-1.64 -5.441
$`5`
Average marginal effects
lm(formula = mpg ~ cyl + wt, data = x)
cyl wt
-0.8501 -6.09
> summary(lstMargins[[1]])
factor AME SE z p lower upper
cyl -0.8380 0.5773 -1.4515 0.1466 -1.9695 0.2936
wt -2.4727 0.8228 -3.0051 0.0027 -4.0855 -0.8600
It would be nice if this worked better so I'll leave it open for the time being but that's the simplest solution at the time being. If you built the original list using a for
loop rather than lapply()
, it would probably also work out of the box.
Install the latest version from GitHub and you should be able to > (lstMargins <- mapply(margins, model = lstFits, data = lstData, SIMPLIFY = FALSE))
$`3`
Average marginal effects
lm(formula = mpg ~ cyl + wt, data = x)
cyl wt
-0.838 -2.473
$`4`
Average marginal effects
lm(formula = mpg ~ cyl + wt, data = x)
cyl wt
-1.64 -5.441
$`5`
Average marginal effects
lm(formula = mpg ~ cyl + wt, data = x)
cyl wt
-0.8501 -6.09
> summary(lstMargins[[1]])
factor AME SE z p lower upper
cyl -0.8380 0.5773 -1.4515 0.1466 -1.9695 0.2936
wt -2.4727 0.8228 -3.0051 0.0027 -4.0855 -0.8600 It would be nice if this worked better so I'll leave it open for the time being but that's the simplest solution at the time being. If you built the original list using a |
This comment has been minimized.
Show comment
Hide comment
This comment has been minimized.
AnttiSim
commented
May 12, 2018
Wonderful! The mapply solution works fine for me. |
This comment has been minimized.
Show comment
Hide comment
This comment has been minimized.
mikedecr
Jun 18, 2018
Hi, I'm running into a similar problem when I try to run this on a list column using a dplyr/tidyr/purrr approach. I'm admittedly not very experienced with the package so maybe I'm doing something fundamentally wrong but here's an example. Sorry for the lengthy code block, but just want to show you different behaviors.
library("magrittr")
library("tidyr")
library("dplyr")
library("purrr")
library("margins")
# attempt to apply margins() across a list column of lm results
# create list column of datasets
# map lm() into each dataset
ests <- mtcars %>%
gather(key = yvar, value = y, vs, am) %>%
group_by(yvar) %>%
nest(.key = model_data) %>%
mutate(mod = map(model_data, ~ lm(y ~ mpg, data = .x)))
# first try using lapply()
ests %$%
lapply(mod, margins)
## Error in eval(model[["call"]][["data"]], env) : object '.x' not found
traceback()
## 20: eval(model[["call"]][["data"]], env)
## 19: eval(model[["call"]][["data"]], env)
## 18: find_data.lm(model, parent.frame())
## 17: find_data(model, parent.frame())
## 16: build_datalist(data, at = at)
## 15: margins.lm(X[[i]], ...)
## 14: FUN(X[[i]], ...)
## 13: lapply(mod, margins)
## 12: eval(substitute(expr), data, enclos = parent.frame())
## 11: eval(substitute(expr), data, enclos = parent.frame())
## 10: with.default(., lapply(mod, margins))
## 9: with(., lapply(mod, margins))
## 8: function_list[[k]](value)
## 7: withVisible(function_list[[k]](value))
## 6: freduce(value, `_function_list`)
## 5: `_fseq`(`_lhs`)
## 4: eval(quote(`_fseq`(`_lhs`)), env, env)
## 3: eval(quote(`_fseq`(`_lhs`)), env, env)
## 2: withVisible(eval(quote(`_fseq`(`_lhs`)), env, env))
## 1: ests %$% lapply(mod, margins)
# supplying data argument
ests %$%
lapply(mod, margins, data = model_data)
## output:
## Error in rep(NA_real_, nrow(data)) : invalid 'times' argument
## In addition: Warning message:
## In dydx.default(X[[i]], ...) :
## Class of variable, mpg, is unrecognized. Returning NA.
traceback()
## 21: dydx.default(X[[i]], ...)
## 20: FUN(X[[i]], ...)
## 19: lapply(c(varslist$nnames, varslist$lnames), dydx, data = data,
## model = model, type = type, eps = eps, as.data.frame = as.data.frame,
## ...)
## 18: marginal_effects.lm(model = model, data = data, variables = variables,
## type = type, eps = eps, varslist = varslist, ...)
## 17: marginal_effects(model = model, data = data, variables = variables,
## type = type, eps = eps, varslist = varslist, ...)
## 16: build_margins(model = model, data = data_list[[i]], variables = variables,
## type = type, vcov = vcov, vce = vce, iterations = iterations,
## unit_ses = unit_ses, eps = eps, varslist = varslist, ...)
## 15: margins.lm(X[[i]], ...)
## 14: FUN(X[[i]], ...)
## 13: lapply(mod, margins, data = model_data)
## 12: eval(substitute(expr), data, enclos = parent.frame())
## 11: eval(substitute(expr), data, enclos = parent.frame())
## 10: with.default(., lapply(mod, margins, data = model_data))
## 9: with(., lapply(mod, margins, data = model_data))
## 8: function_list[[k]](value)
## 7: withVisible(function_list[[k]](value))
## 6: freduce(value, `_function_list`)
## 5: `_fseq`(`_lhs`)
## 4: eval(quote(`_fseq`(`_lhs`)), env, env)
## 3: eval(quote(`_fseq`(`_lhs`)), env, env)
## 2: withVisible(eval(quote(`_fseq`(`_lhs`)), env, env))
## 1: ests %$% lapply(mod, margins, data = model_data)
# using mapply() approach
ests %$%
mapply(margins, mod, data = model_data)
## Output:
## [,1] [,2]
## mpg Numeric,32 Numeric,32
## cyl Numeric,32 Numeric,32
## disp Numeric,32 Numeric,32
## hp Numeric,32 Numeric,32
## drat Numeric,32 Numeric,32
## wt Numeric,32 Numeric,32
## qsec Numeric,32 Numeric,32
## gear Numeric,32 Numeric,32
## carb Numeric,32 Numeric,32
## y Numeric,32 Numeric,32
## fitted Numeric,32 Numeric,32
## se.fitted Numeric,32 Numeric,32
## dydx_mpg Numeric,32 Numeric,32
## Var_dydx_mpg Numeric,32 Numeric,32
## _weights Numeric,32 Numeric,32
## _at_number Integer,32 Integer,32
# not an error just not what I thought I should get
# could be my own ignorance about the behavior of the package
# attempt using map()
ests %>%
mutate(marginals = map(mod, margins))
## Output:
## Error in mutate_impl(.data, dots) :
## Evaluation error: invalid 'times' argument.
## In addition: Warning message:
## In dydx.default(X[[i]], ...) :
## Class of variable, mpg, is unrecognized. Returning NA.
traceback()
## Output:
## 12: stop(list(message = "Evaluation error: invalid 'times' argument.",
## call = mutate_impl(.data, dots), cppstack = NULL))
## 11: mutate_impl(.data, dots)
## 10: mutate.tbl_df(., marginals = map(mod, margins))
## 9: mutate(., marginals = map(mod, margins))
## 8: function_list[[k]](value)
## 7: withVisible(function_list[[k]](value))
## 6: freduce(value, `_function_list`)
## 5: `_fseq`(`_lhs`)
## 4: eval(quote(`_fseq`(`_lhs`)), env, env)
## 3: eval(quote(`_fseq`(`_lhs`)), env, env)
## 2: withVisible(eval(quote(`_fseq`(`_lhs`)), env, env))
## 1: ests %>% mutate(marginals = map(mod, margins))
# attempt when supplying data using map2()
ests %>%
mutate(marginals = map2(mod, model_data, ~ margins(.x, data = .y))) %>%
select(marginals) %>%
unnest()
# I won't paste the full output but this returns a tibble
# with original data and appended columns `fitted`, `se.fitted`, and so on
# not the typical output of margins()
# goal: hoping to get output as a list something like this
list(margins(lm(vs ~ mpg, data = mtcars)),
margins(lm(am ~ mpg, data = mtcars)))
sessionInfo()
R version 3.5.0 (2018-04-23)
Platform: x86_64-apple-darwin15.6.0 (64-bit)
Running under: macOS High Sierra 10.13.5
Matrix products: default
BLAS: /Library/Frameworks/R.framework/Versions/3.5/Resources/lib/ libRblas.0.dylib
LAPACK: /Library/Frameworks/R.framework/Versions/3.5/Resources/lib/ libRlapack.dylib
locale:
[1] en_US.UTF-8/en_US.UTF-8/en_US.UTF-8/C/en_US.UTF-8/en_US.UTF-8
attached base packages:
[1] stats graphics grDevices utils datasets methods base
other attached packages:
[1] bindrcpp_0.2.2 margins_0.3.23 purrr_0.2.4 dplyr_0.7.4 tidyr_0.8.0
[6] magrittr_1.5
loaded via a namespace (and not attached):
[1] Rcpp_0.12.16 utf8_1.1.3 crayon_1.3.4 assertthat_0.2.0
[5] MASS_7.3-49 R6_2.2.2 pillar_1.2.2 cli_1.0.0
[9] rlang_0.2.0 data.table_1.11.4 prediction_0.3.6 glue_1.2.0
[13] compiler_3.5.0 pkgconfig_2.0.1 tidyselect_0.2.4 bindr_0.1.1
[17] tibble_1.4.2
mikedecr
commented
Jun 18, 2018
Hi, I'm running into a similar problem when I try to run this on a list column using a dplyr/tidyr/purrr approach. I'm admittedly not very experienced with the package so maybe I'm doing something fundamentally wrong but here's an example. Sorry for the lengthy code block, but just want to show you different behaviors. library("magrittr")
library("tidyr")
library("dplyr")
library("purrr")
library("margins")
# attempt to apply margins() across a list column of lm results
# create list column of datasets
# map lm() into each dataset
ests <- mtcars %>%
gather(key = yvar, value = y, vs, am) %>%
group_by(yvar) %>%
nest(.key = model_data) %>%
mutate(mod = map(model_data, ~ lm(y ~ mpg, data = .x)))
# first try using lapply()
ests %$%
lapply(mod, margins)
## Error in eval(model[["call"]][["data"]], env) : object '.x' not found
traceback()
## 20: eval(model[["call"]][["data"]], env)
## 19: eval(model[["call"]][["data"]], env)
## 18: find_data.lm(model, parent.frame())
## 17: find_data(model, parent.frame())
## 16: build_datalist(data, at = at)
## 15: margins.lm(X[[i]], ...)
## 14: FUN(X[[i]], ...)
## 13: lapply(mod, margins)
## 12: eval(substitute(expr), data, enclos = parent.frame())
## 11: eval(substitute(expr), data, enclos = parent.frame())
## 10: with.default(., lapply(mod, margins))
## 9: with(., lapply(mod, margins))
## 8: function_list[[k]](value)
## 7: withVisible(function_list[[k]](value))
## 6: freduce(value, `_function_list`)
## 5: `_fseq`(`_lhs`)
## 4: eval(quote(`_fseq`(`_lhs`)), env, env)
## 3: eval(quote(`_fseq`(`_lhs`)), env, env)
## 2: withVisible(eval(quote(`_fseq`(`_lhs`)), env, env))
## 1: ests %$% lapply(mod, margins)
# supplying data argument
ests %$%
lapply(mod, margins, data = model_data)
## output:
## Error in rep(NA_real_, nrow(data)) : invalid 'times' argument
## In addition: Warning message:
## In dydx.default(X[[i]], ...) :
## Class of variable, mpg, is unrecognized. Returning NA.
traceback()
## 21: dydx.default(X[[i]], ...)
## 20: FUN(X[[i]], ...)
## 19: lapply(c(varslist$nnames, varslist$lnames), dydx, data = data,
## model = model, type = type, eps = eps, as.data.frame = as.data.frame,
## ...)
## 18: marginal_effects.lm(model = model, data = data, variables = variables,
## type = type, eps = eps, varslist = varslist, ...)
## 17: marginal_effects(model = model, data = data, variables = variables,
## type = type, eps = eps, varslist = varslist, ...)
## 16: build_margins(model = model, data = data_list[[i]], variables = variables,
## type = type, vcov = vcov, vce = vce, iterations = iterations,
## unit_ses = unit_ses, eps = eps, varslist = varslist, ...)
## 15: margins.lm(X[[i]], ...)
## 14: FUN(X[[i]], ...)
## 13: lapply(mod, margins, data = model_data)
## 12: eval(substitute(expr), data, enclos = parent.frame())
## 11: eval(substitute(expr), data, enclos = parent.frame())
## 10: with.default(., lapply(mod, margins, data = model_data))
## 9: with(., lapply(mod, margins, data = model_data))
## 8: function_list[[k]](value)
## 7: withVisible(function_list[[k]](value))
## 6: freduce(value, `_function_list`)
## 5: `_fseq`(`_lhs`)
## 4: eval(quote(`_fseq`(`_lhs`)), env, env)
## 3: eval(quote(`_fseq`(`_lhs`)), env, env)
## 2: withVisible(eval(quote(`_fseq`(`_lhs`)), env, env))
## 1: ests %$% lapply(mod, margins, data = model_data)
# using mapply() approach
ests %$%
mapply(margins, mod, data = model_data)
## Output:
## [,1] [,2]
## mpg Numeric,32 Numeric,32
## cyl Numeric,32 Numeric,32
## disp Numeric,32 Numeric,32
## hp Numeric,32 Numeric,32
## drat Numeric,32 Numeric,32
## wt Numeric,32 Numeric,32
## qsec Numeric,32 Numeric,32
## gear Numeric,32 Numeric,32
## carb Numeric,32 Numeric,32
## y Numeric,32 Numeric,32
## fitted Numeric,32 Numeric,32
## se.fitted Numeric,32 Numeric,32
## dydx_mpg Numeric,32 Numeric,32
## Var_dydx_mpg Numeric,32 Numeric,32
## _weights Numeric,32 Numeric,32
## _at_number Integer,32 Integer,32
# not an error just not what I thought I should get
# could be my own ignorance about the behavior of the package
# attempt using map()
ests %>%
mutate(marginals = map(mod, margins))
## Output:
## Error in mutate_impl(.data, dots) :
## Evaluation error: invalid 'times' argument.
## In addition: Warning message:
## In dydx.default(X[[i]], ...) :
## Class of variable, mpg, is unrecognized. Returning NA.
traceback()
## Output:
## 12: stop(list(message = "Evaluation error: invalid 'times' argument.",
## call = mutate_impl(.data, dots), cppstack = NULL))
## 11: mutate_impl(.data, dots)
## 10: mutate.tbl_df(., marginals = map(mod, margins))
## 9: mutate(., marginals = map(mod, margins))
## 8: function_list[[k]](value)
## 7: withVisible(function_list[[k]](value))
## 6: freduce(value, `_function_list`)
## 5: `_fseq`(`_lhs`)
## 4: eval(quote(`_fseq`(`_lhs`)), env, env)
## 3: eval(quote(`_fseq`(`_lhs`)), env, env)
## 2: withVisible(eval(quote(`_fseq`(`_lhs`)), env, env))
## 1: ests %>% mutate(marginals = map(mod, margins))
# attempt when supplying data using map2()
ests %>%
mutate(marginals = map2(mod, model_data, ~ margins(.x, data = .y))) %>%
select(marginals) %>%
unnest()
# I won't paste the full output but this returns a tibble
# with original data and appended columns `fitted`, `se.fitted`, and so on
# not the typical output of margins()
# goal: hoping to get output as a list something like this
list(margins(lm(vs ~ mpg, data = mtcars)),
margins(lm(am ~ mpg, data = mtcars)))
sessionInfo() R version 3.5.0 (2018-04-23) Matrix products: default locale: attached base packages: other attached packages: loaded via a namespace (and not attached): |
This comment has been minimized.
Show comment
Hide comment
This comment has been minimized.
leeper
Jun 18, 2018
Owner
@mikedecr The mapply()
strategy should work in your case, but you need to pass the SIMPLIFY = FALSE
argument - that's why you're getting the confusing "matrix of lists" result.
Though I'm not a purrr expert, I think the map2()
function might also work for you in this case.
@mikedecr The Though I'm not a purrr expert, I think the |
This comment has been minimized.
Show comment
Hide comment
This comment has been minimized.
leeper
Jun 18, 2018
Owner
@mikedecr And I see you already tried that. The result is probably what you want - margins()
returns a data frame and summary(margins())
returns the data frame of AMEs and standard errors that I imagine you'd like to obtain.
I might also be able to suggest something else if I have a better sense of the big picture. You say you have a list column - are you bootstrapping or something similar?
@mikedecr And I see you already tried that. The result is probably what you want - I might also be able to suggest something else if I have a better sense of the big picture. You say you have a list column - are you bootstrapping or something similar? |
This comment has been minimized.
Show comment
Hide comment
This comment has been minimized.
mikedecr
Jun 18, 2018
@leeper Thanks, I think I was a little confused because sometimes I would run margins()
on a dummy example and get the summary-style output, but I was getting the data frame in my application. Using map2()
and including the additional summary()
appears to give me what I'm looking for. I'll test it with another simple example and let you know if it doesn't work out, but in case you don't hear back from me, you can consider my problem addressed! Thanks for the clarification, this is gonna be a huge help for what I'm currently hacking through.
mikedecr
commented
Jun 18, 2018
@leeper Thanks, I think I was a little confused because sometimes I would run |
This comment has been minimized.
Show comment
Hide comment
This comment has been minimized.
leeper
Jul 22, 2018
Owner
I've just added a new function to the package - margins_summary(...)
- that provides simple sugar for the nested expression summary(margins(...))
so that you obtain a probably more-expected result in situations such as this. I've also added some examples based upon this issue to ? margins
showcasing functionality.
I've just added a new function to the package - |
leeper
closed this
in
3f32640
Jul 22, 2018
This comment has been minimized.
Show comment
Hide comment
This comment has been minimized.
NEN11
Aug 1, 2018
I got a similar error message when using the cplot() function:
error in eval(model[["call"]][["data"]], env) :
promise already under evaluation: recursive default argument reference or earlier problems?
I figured out that if your own data frame is named "data" and used in the regression glm() function, then cplot() gives the error above...
(this post is not related to the issues above....)
NEN11
commented
Aug 1, 2018
•
I got a similar error message when using the cplot() function: error in eval(model[["call"]][["data"]], env) : I figured out that if your own data frame is named "data" and used in the regression glm() function, then cplot() gives the error above... (this post is not related to the issues above....) |
This comment has been minimized.
Show comment
Hide comment
This comment has been minimized.
@NEN11 can you please open a new issue? |
AnttiSim commentedMay 11, 2018
•
edited
Edited 1 time
-
AnttiSim
edited May 11, 2018 (most recent)
Please specify whether your issue is about:
Hi,
I have a list of glm model fits. I tried to apply margins for each item in the list with lapply. That however terminates with an error. Choosing one item from the list returns the same error.
I could reproduce that with a simple lm model (see below).
Put your code here:
R version 3.5.0 (2018-04-23)
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=Finnish_Finland.1252 LC_CTYPE=Finnish_Finland.1252
[3] LC_MONETARY=Finnish_Finland.1252 LC_NUMERIC=C
[5] LC_TIME=Finnish_Finland.1252
attached base packages:
[1] stats graphics grDevices utils datasets tcltk methods
[8] base
other attached packages:
[1] bindrcpp_0.2.2 stargazer_5.2.1 lmtest_0.9-36 zoo_1.8-1
[5] sandwich_2.4-0 forcats_0.3.0 stringr_1.3.0 dplyr_0.7.4
[9] purrr_0.2.4 readr_1.1.1 tidyr_0.8.0 tibble_1.4.2
[13] ggplot2_2.2.1 tidyverse_1.2.1
loaded via a namespace (and not attached):
[1] Rcpp_0.12.16 cellranger_1.1.0 pillar_1.2.2 compiler_3.5.0
[5] plyr_1.8.4 bindr_0.1.1 tools_3.5.0 lubridate_1.7.4
[9] jsonlite_1.5 nlme_3.1-137 gtable_0.2.0 lattice_0.20-35
[13] pkgconfig_2.0.1 rlang_0.2.0 psych_1.8.4 cli_1.0.0
[17] rstudioapi_0.7 parallel_3.5.0 haven_1.1.1 xml2_1.2.0
[21] httr_1.3.1 hms_0.4.2 tidyselect_0.2.4 grid_3.5.0
[25] glue_1.2.0 R6_2.2.2 readxl_1.1.0 foreign_0.8-70
[29] modelr_0.1.1 reshape2_1.4.3 magrittr_1.5 scales_0.5.0
[33] rvest_0.3.2 assertthat_0.2.0 mnormt_1.5-5 colorspace_1.3-2
[37] stringi_1.2.2 lazyeval_0.2.1 munsell_0.4.3 broom_0.4.4
[41] crayon_1.3.4