I am trying to adapt boxplot.formula (in graphics) to accept an additional parameter, weights. I already managed to adapt boxplot.default to do this. boxplot.formula prepares the data for a call to boxplot.default and to achieve that does the following: It takes a formula like x~g*h as the first argument, and then by using m <- match.call(expand.dots = FALSE) saves the call. It transforms the call m$na.action <- na.action # force use of default for this method m[[1]] <- as.name("model.frame") and then evaluates the modified call mf <- eval(m, parent.frame()) print(m) gives model.frame(formula = x ~ g * h) Then it uses components of mf for the call to boxplot.default. m has a component m$formula containing the parsed model formula. mode(m$formula) is "call". In our case, deparse(m$formula) gives a string representation of the formula: "x~g*h". I want to replace the response variable (in our case x) by the weights variable, which in the string expression can be done easily with strsplit and paste. Then I need to reconvert the modified string to a call. So I create newmodelstring<-"weights~g*h" and try m$formula<-as.call(parse(newmodelstring)) print(m) gives model.frame(formula = weights ~ g * h()) When I try to evaluate the modified m this does not work. When I try to evaluate m with this modification I get Error in model.frame(formula = weights ~ g * h()) : attempt to apply non-function Is there a way to get rid of the empty parentheses at the end of the formula? I think then my code could work. -- Erich Neuwirth, Didactic Center for Computer Science University of Vienna Visit our SunSITE at http://sunsite.univie.ac.at Phone: +43-1-4277-39902 Fax: +43-1-4277-9399
On 8/22/05, Erich Neuwirth <erich.neuwirth at univie.ac.at> wrote:> I am trying to adapt boxplot.formula (in graphics) to accept an > additional parameter, weights. > I already managed to adapt boxplot.default to do this. > > boxplot.formula prepares the data for a call to boxplot.default and to > achieve that does the following: It takes a formula like > > x~g*h > > as the first argument, and then by using > > m <- match.call(expand.dots = FALSE) > > saves the call. It transforms the call > > m$na.action <- na.action # force use of default for this method > m[[1]] <- as.name("model.frame") > > and then evaluates the modified call > mf <- eval(m, parent.frame()) > > print(m) > gives > model.frame(formula = x ~ g * h) > > Then it uses components of mf for the call to boxplot.default. > > m has a component m$formula containing the parsed model formula. > mode(m$formula) is "call". > In our case, deparse(m$formula) gives a string representation of the > formula: "x~g*h". > I want to replace the response variable (in our case x) by the weights > variable, which in the string expression can be done easily with > strsplit and paste. Then I need to reconvert the modified string to a call. > > So I create newmodelstring<-"weights~g*h" and try > > m$formula<-as.call(parse(newmodelstring)) > > print(m) > gives > model.frame(formula = weights ~ g * h()) > > > When I try to evaluate the modified m this does not work. When I try to > evaluate m with this modification I get > > Error in model.frame(formula = weights ~ g * h()) : > attempt to apply non-function > > Is there a way to get rid of the empty parentheses at the > end of the formula? I think then my code could work. > > -- > Erich Neuwirth, Didactic Center for Computer Science > University of Vienna > Visit our SunSITE at http://sunsite.univie.ac.at > Phone: +43-1-4277-39902 Fax: +43-1-4277-9399 > > ______________________________________________ > R-devel at r-project.org mailing list > https://stat.ethz.ch/mailman/listinfo/r-devel >I think the preferred way to do this is using substitute although formulas are a bit tricky in that you need to eval them after the substitution to make sure that the object has class "formula".> (foo <- eval(substitute(x ~ g * h, list(x = as.name("weights")))))weights ~ g * h> class(foo)[1] "formula"
> >>(foo <- eval(substitute(x ~ g * h, list(x = as.name("weights"))))) > > weights ~ g * h > >>class(foo) > > [1] "formula" > >ff<-formula("x~g*h") (foo<-eval(substitute(ff,list(x=as.name("weights"))))) gives x ~ g * h what needs to be done to ff for the substitution to work? I found a way of doing it using string substitution and applying formula (instead of as.call) to the string, but I would like to be able to do it using substitution. This is what I currently do: myexpr<-paste("weights ~",strsplit(deparse(m$formula),"~")[[1]][2]) m$formula<-formula(myexpr) -- Erich Neuwirth, Didactic Center for Computer Science University of Vienna Visit our SunSITE at http://sunsite.univie.ac.at Phone: +43-1-4277-39902 Fax: +43-1-4277-9399
On 8/22/05, Erich Neuwirth <erich.neuwirth at univie.ac.at> wrote:> > > >>(foo <- eval(substitute(x ~ g * h, list(x = as.name("weights"))))) > > > > weights ~ g * h > > > >>class(foo) > > > > [1] "formula" > > > > > > ff<-formula("x~g*h") > (foo<-eval(substitute(ff,list(x=as.name("weights"))))) > > gives > > x ~ g * h > > what needs to be done to ff for the substitution to work? > > I found a way of doing it using string substitution > and applying formula (instead of as.call) to the string, > but I would like to be able to do it using substitution. > > This is what I currently do: > > myexpr<-paste("weights ~",strsplit(deparse(m$formula),"~")[[1]][2]) > m$formula<-formula(myexpr)Try do.call like this: ff <- x ~ g*h do.call("substitute", list(ff, list(x = as.name("weight"))))
> Try do.call like this: > > ff <- x ~ g*h > do.call("substitute", list(ff, list(x = as.name("weight")))) >It is even more complicated. All I know is that ff is a formula with an expression on the left hand side. This expression needs to be replaced by "weights". According to the documentation, substitute only handles replacement of variables by something else, and that is not enough in my case. -- Erich Neuwirth, Didactic Center for Computer Science University of Vienna Visit our SunSITE at http://sunsite.univie.ac.at Phone: +43-1-4277-39902 Fax: +43-1-4277-9399