msm icon indicating copy to clipboard operation
msm copied to clipboard

HMM model constructors seem to only allow literal constraints

Open lbakerIsazi opened this issue 7 years ago • 5 comments

The following code produces an error:

lapply(c(1,2,3), function(y) hmmNorm(mean = y, sd = 0.5))

This sort of construction would be quite common when using the msm package with a variable number of states.

lbakerIsazi avatar Oct 05 '17 14:10 lbakerIsazi

The following code also produces an error:

t <- 1
hmmNorm(mean = t, sd = 3)

lbakerIsazi avatar Oct 05 '17 14:10 lbakerIsazi

Thanks for the report. I'll clarify the documentation in help(hmm-dists). I agree it would be nice to support variables here, but I think some tricky "computing on the language" would be required to fix this. Any suggestions are welcome.

chjackson avatar Oct 06 '17 09:10 chjackson

Thanks for the feedback. Unfortunately I'm not good enough with R yet to be sure of how to fix this. Here's what I think is going on:

In the code above, when the constructor for hmmNorm gets to hmmDist in R/hmm-dists.R and eval is called, it's looking for the variable t in the current environment, where it doesn't exist. One parameter to eval is envir, which is parent.frame(1) by default. If parent.frame(2) or parent.frame(3) is specified instead, it will look up that many generations in the call stack - maybe this can be used to look fr the value of t in the environment wherein hmmNorm was called?

In the meantime, here's a workaround/hack (which won't work for the variable name t, unfortunately, since it's already the name of a base function):

b <<- 1
d << 0.5
h <- hmmNorm(b,d)

This works since b and d are then defined in the global scope and so eval doesn't have any trouble finding their values.

lbakerIsazi avatar Oct 06 '17 12:10 lbakerIsazi

Hello @lbakerIsazi, the lift_*() functions from the purrr package can help in this situation. For instance:

lapply(c(1,2,3), function(y) purrr::lift_dl(hmmNorm)(mean = y, sd = 0.5))

will behave as you need. lift_dl(hmmNorm) is converting hmmNorm from a function that accepts ... (or dots, hence the d) as its argument to a function that accepts a list (hence the l) as its argument. You can see more info at https://purrr.tidyverse.org/reference/lift.html

wjchulme avatar Feb 11 '19 16:02 wjchulme

A few updates here. I also encountered this, but bare variables now work (presumably due to R interpreter?). In addition to @wjchulme's suggestion, another workaround is to directly edit the attributes of the function post-construction.

## works in R 4.0.4, msm_1.6.9
val <- 0.2
obs.var <- hmmBinom(size=1, prob=val)

##  also works
l.obs.sub <- lapply(seq(0.1, 0.9, by=0.1), function(x) {
    ret <- hmmBinom(size=1, prob=1)
    ret$pars['prob']  <- x
    ret
})

helmingstay avatar Dec 09 '21 04:12 helmingstay