Suppose I have a formula like this:
f <- y ~ qss(x, lambda = lambdas[1]) + qss(z, lambdas[2]) + s
I?d like a function, g(lambdas, f) that would take g(c(2,3), f) and produce the
new
formula:
y ~ qss(x, lambda = 2) + qss(z, 3) + s
For only two qss terms I have been using
g <- function(lambdas, f){
F <- deparse(f)
F <- gsub("lambdas\\[1\\]",lambdas[1],F)
F <- gsub("lambdas\\[2\\]",lambdas[2],F)
formula(F)
}
but this is ugly and doesn?t extend nicely to more qss terms. Isn?t there some
bquote() magic that can be invoked? Or something else entirely?
Recursively walk the formula performing the replacement:
g <- function(e, ...) {
if (length(e) > 1) {
if (identical(e[[2]], as.name(names(list(...))))) {
e <- eval(e, list(...))
}
if (length(e) > 1) for (i in 1:length(e)) e[[i]] <- Recall(e[[i]],
...)
}
e
}
g(f, lambdas = 2:3)
## y ~ qss(x, lambda = 2L) + qss(z, 3L) + s
On Fri, Oct 23, 2020 at 9:33 AM Koenker, Roger W <rkoenker at
illinois.edu> wrote:>
> Suppose I have a formula like this:
>
> f <- y ~ qss(x, lambda = lambdas[1]) + qss(z, lambdas[2]) + s
>
> I?d like a function, g(lambdas, f) that would take g(c(2,3), f) and
produce the new
> formula:
>
> y ~ qss(x, lambda = 2) + qss(z, 3) + s
>
> For only two qss terms I have been using
>
> g <- function(lambdas, f){
> F <- deparse(f)
> F <- gsub("lambdas\\[1\\]",lambdas[1],F)
> F <- gsub("lambdas\\[2\\]",lambdas[2],F)
> formula(F)
> }
> but this is ugly and doesn?t extend nicely to more qss terms. Isn?t there
some
> bquote() magic that can be invoked? Or something else entirely?
> ______________________________________________
> R-help at r-project.org mailing list -- To UNSUBSCRIBE and more, see
> https://stat.ethz.ch/mailman/listinfo/r-help
> PLEASE do read the posting guide
http://www.R-project.org/posting-guide.html
> and provide commented, minimal, self-contained, reproducible code.
--
Statistics & Software Consulting
GKX Group, GKX Associates Inc.
tel: 1-877-GKX-GROUP
email: ggrothendieck at gmail.com
Thanks, Gabor! Very elegant!> On Oct 23, 2020, at 4:15 PM, Gabor Grothendieck <ggrothendieck at gmail.com> wrote: > > Recursively walk the formula performing the replacement: > > g <- function(e, ...) { > if (length(e) > 1) { > if (identical(e[[2]], as.name(names(list(...))))) { > e <- eval(e, list(...)) > } > if (length(e) > 1) for (i in 1:length(e)) e[[i]] <- Recall(e[[i]], ...) > } > e > } > > g(f, lambdas = 2:3) > ## y ~ qss(x, lambda = 2L) + qss(z, 3L) + s > > On Fri, Oct 23, 2020 at 9:33 AM Koenker, Roger W <rkoenker at illinois.edu> wrote: >> >> Suppose I have a formula like this: >> >> f <- y ~ qss(x, lambda = lambdas[1]) + qss(z, lambdas[2]) + s >> >> I?d like a function, g(lambdas, f) that would take g(c(2,3), f) and produce the new >> formula: >> >> y ~ qss(x, lambda = 2) + qss(z, 3) + s >> >> For only two qss terms I have been using >> >> g <- function(lambdas, f){ >> F <- deparse(f) >> F <- gsub("lambdas\\[1\\]",lambdas[1],F) >> F <- gsub("lambdas\\[2\\]",lambdas[2],F) >> formula(F) >> } >> but this is ugly and doesn?t extend nicely to more qss terms. Isn?t there some >> bquote() magic that can be invoked? Or something else entirely? >> ______________________________________________ >> R-help at r-project.org mailing list -- To UNSUBSCRIBE and more, see >> https://stat.ethz.ch/mailman/listinfo/r-help >> PLEASE do read the posting guide http://www.R-project.org/posting-guide.html >> and provide commented, minimal, self-contained, reproducible code. > > > > -- > Statistics & Software Consulting > GKX Group, GKX Associates Inc. > tel: 1-877-GKX-GROUP > email: ggrothendieck at gmail.com
I can't compete with Gabor's "elegant" solution, but I
don't understand why
your original "ugly" approach doesn't work.
g <- function(lambdas, f){
z <- as.character(f)
for(i in seq_along(lambdas))
z[3]<- sub(paste0("lambdas[", i, "]"), lambdas[i],
z[3], fixed TRUE)
formula(paste0(z[c(2,1,3)], collapse = " "))
}
> f <- y ~ qss(x, lambda = lambdas[1]) + qss(z, lambdas[2]) + s
> g(1:2, f)
y ~ qss(x, lambda = 1) + qss(z, 2) + s
<environment: 0x7f930e768598>
> f <- y ~ qss(x, lambda = lambdas[1]) + qss(z, lambdas[2]) +
+ qss(z,lambdas[3]) + s> g(3:1, f)
y ~ qss(x, lambda = 3) + qss(z, 2) + qss(z, 1) + s
<environment: 0x7f930e7404f0>
Is there maybe a problem with the environment of the created formula? Or
have I misunderstood what you wanted?
Cheers,
Bert
Bert Gunter
"The trouble with having an open mind is that people keep coming along and
sticking things into it."
-- Opus (aka Berkeley Breathed in his "Bloom County" comic strip )
On Fri, Oct 23, 2020 at 6:33 AM Koenker, Roger W <rkoenker at
illinois.edu>
wrote:
> Suppose I have a formula like this:
>
> f <- y ~ qss(x, lambda = lambdas[1]) + qss(z, lambdas[2]) + s
>
> I?d like a function, g(lambdas, f) that would take g(c(2,3), f) and
> produce the new
> formula:
>
> y ~ qss(x, lambda = 2) + qss(z, 3) + s
>
> For only two qss terms I have been using
>
> g <- function(lambdas, f){
> F <- deparse(f)
> F <- gsub("lambdas\\[1\\]",lambdas[1],F)
> F <- gsub("lambdas\\[2\\]",lambdas[2],F)
> formula(F)
> }
> but this is ugly and doesn?t extend nicely to more qss terms. Isn?t there
> some
> bquote() magic that can be invoked? Or something else entirely?
> ______________________________________________
> R-help at r-project.org mailing list -- To UNSUBSCRIBE and more, see
> https://stat.ethz.ch/mailman/listinfo/r-help
> PLEASE do read the posting guide
> http://www.R-project.org/posting-guide.html
> and provide commented, minimal, self-contained, reproducible code.
>
[[alternative HTML version deleted]]