Re: [R] a question of substitute
Dear Prof. Ripley, Thank you for this extensive explanation. It looks like my first solution is similar to (b): creating new variables inside the wrapper (and new data if not missing). This course is only introductory, with simple models, and I do point students to each test separately if they want more complicated things. I'm looking forward to the release of the 2.5.0 version. Best regards, Adrian On Thursday 11 January 2007 03:08, Prof Brian Ripley wrote: The 'Right Thing' is for oneway.test() to allow a variable for the first argument, and I have altered it in R-patched and R-devel to do so. So if your students can make use of R-patched that would be the best solution. If not, perhaps you could make a copy of oneway.test from R-patched available to them. Normally I would worry about namespace issues, but it seems unlikely they would matter here: if they did assignInNamespace is likely to work to insert the fix. Grothendieck's suggestions are steps towards a morass: they may work in simple cases but can make more complicated ones worse (such as looking for 'data' in the wrong place). These model fitting functions have rather precise requirements for where they look for their components: 'data' the environment of 'formula' the environment of the caller and that includes where they look for 'data'. It is easy to use substitute or such to make a literal formula out of 'formula', but doing so changes its environment. So one needs to either (a) fix up an environment within which to evaluate the modified call that emulates the scoping rules or (b) create a new 'data' that has references to all the variables needed, and just call the function with the new 'formula' and new 'data'. At first sight model.frame() looks the way to do (b), but it is not, since if there are function calls in the formula (e.g. log()) the model frame includes the derived variables and not the original ones. There are workarounds (e.g. in glmmPQL), like using all.vars, creating a formula from that, setting its environment to that of the original function and then calling model.frame. This comes up often enough that I have contemplated adding a solution to (b) to the stats package. Doing either of these right is really pretty complicated, and not something to dash off code in a fairly quick reply (or even to check that the code in glmmPQL was general enough to be applicable). -- Adrian Dusa Romanian Social Data Archive 1, Schitu Magureanu Bd 050025 Bucharest sector 5 Romania Tel./Fax: +40 21 3126618 \ +40 21 3120210 / int.101 __ R-help@stat.math.ethz.ch mailing list 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.
Re: [R] a question of substitute
Looks like oneway.test has been changed for R 2.5.0. Paste the code in this file: https://svn.r-project.org/R/trunk/src/library/stats/R/oneway.test.R into your session. Then fun.2 from your post will work without the workarounds I posted: fun.2(values ~ group) On 1/9/07, Adrian Dusa [EMAIL PROTECTED] wrote: On Tuesday 09 January 2007 15:14, Gabor Grothendieck wrote: oneway.test is using substitute on its arguments so its literally getting formula rather than the value of formula. Ah-haa... I understand now. Thanks for the tips, they both work as expected. Best, Adrian Try these: fun.3 - function(formula) { mc - match.call() mc[[1]] - as.name(oneway.test) eval.parent(mc) } fun.3(values ~ group) fun.4 - function(formula) { do.call(oneway.test, list(formula)) } fun.4(values ~ group) On 1/9/07, Adrian Dusa [EMAIL PROTECTED] wrote: Hi all, I want to write a wrapper for an analysis of variance and I face a curious problem. Here are two different wrappers: fun.1 - function(formula) { summary(aov(formula)) } fun.2 - function(formula) { oneway.test(formula) } values - c(15, 8, 17, 7, 26, 12, 8, 11, 16, 9, 16, 24, 20, 19, 9, 17, 11, 8, 15, 6, 14) group - rep(1:3, each=7) # While the first wrapper works just fine: fun.1(values ~ group) # the second throws an error: fun.2(values ~ group) Error in substitute(formula)[[2]] : object is not subsettable ### I also tried binding the two vectors in a data.frame, with no avail. I did find a hack, creating two new vectors inside the function and creating a fresh formula, so I presume this has something to do with environments. Could anybody give me a hint on this? Thank you, Adrian -- Adrian Dusa Romanian Social Data Archive 1, Schitu Magureanu Bd 050025 Bucharest sector 5 Romania Tel./Fax: +40 21 3126618 \ +40 21 3120210 / int.101 __ R-help@stat.math.ethz.ch mailing list 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. -- Adrian Dusa Arhiva Romana de Date Sociale Bd. Schitu Magureanu nr.1 050025 Bucuresti sectorul 5 Romania Tel./Fax: +40 21 3126618 \ +40 21 3120210 / int.101 __ R-help@stat.math.ethz.ch mailing list 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.
Re: [R] a question of substitute
On Wednesday 10 January 2007 19:03, Gabor Grothendieck wrote: Looks like oneway.test has been changed for R 2.5.0. Paste the code in this file: https://svn.r-project.org/R/trunk/src/library/stats/R/oneway.test.R into your session. Then fun.2 from your post will work without the workarounds I posted: fun.2(values ~ group) Brilliant :) Super fast change, this is why I love R. Cheers, Adrian -- Adrian Dusa Romanian Social Data Archive 1, Schitu Magureanu Bd 050025 Bucharest sector 5 Romania Tel./Fax: +40 21 3126618 \ +40 21 3120210 / int.101 __ R-help@stat.math.ethz.ch mailing list 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.
Re: [R] a question of substitute
The 'Right Thing' is for oneway.test() to allow a variable for the first argument, and I have altered it in R-patched and R-devel to do so. So if your students can make use of R-patched that would be the best solution. If not, perhaps you could make a copy of oneway.test from R-patched available to them. Normally I would worry about namespace issues, but it seems unlikely they would matter here: if they did assignInNamespace is likely to work to insert the fix. Grothendieck's suggestions are steps towards a morass: they may work in simple cases but can make more complicated ones worse (such as looking for 'data' in the wrong place). These model fitting functions have rather precise requirements for where they look for their components: 'data' the environment of 'formula' the environment of the caller and that includes where they look for 'data'. It is easy to use substitute or such to make a literal formula out of 'formula', but doing so changes its environment. So one needs to either (a) fix up an environment within which to evaluate the modified call that emulates the scoping rules or (b) create a new 'data' that has references to all the variables needed, and just call the function with the new 'formula' and new 'data'. At first sight model.frame() looks the way to do (b), but it is not, since if there are function calls in the formula (e.g. log()) the model frame includes the derived variables and not the original ones. There are workarounds (e.g. in glmmPQL), like using all.vars, creating a formula from that, setting its environment to that of the original function and then calling model.frame. This comes up often enough that I have contemplated adding a solution to (b) to the stats package. Doing either of these right is really pretty complicated, and not something to dash off code in a fairly quick reply (or even to check that the code in glmmPQL was general enough to be applicable). On Tue, 9 Jan 2007, Adrian Dusa wrote: On Tuesday 09 January 2007 15:41, Prof Brian Ripley wrote: oneway.test expects a literal formula, not a variable containing a formula. The help page says formula: a formula of the form 'lhs ~ rhs' where 'lhs' gives the sample values and 'rhs' the corresponding groups. Furthermore, if you had foo.2 - function() oneway.test(value ~ group) it would still not work, as data: an optional matrix or data frame (or similar: see 'model.frame') containing the variables in the formula 'formula'. By default the variables are taken from 'environment(formula)'. I could show you several complicated workarounds, but why do you want to do this? Thank you for your reply. The data argument was exactly the next problem I faced. My workaround involves checking if(missing(data)) then uses different calls to oneway.test(). I am certainly interested in other solutions, this one is indeed limited. I do this for the students in the anova class, checking first the homogeneity of variances with fligner.test(), printing the p.value and based on that changing the var.equal argument in the oneway.test() It's just for convenience, but they do like having it all-in-one. Best regards, Adrian -- Brian D. Ripley, [EMAIL PROTECTED] Professor of Applied Statistics, http://www.stats.ox.ac.uk/~ripley/ University of Oxford, Tel: +44 1865 272861 (self) 1 South Parks Road, +44 1865 272866 (PA) Oxford OX1 3TG, UKFax: +44 1865 272595 __ R-help@stat.math.ethz.ch mailing list 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.
Re: [R] a question of substitute
oneway.test is using substitute on its arguments so its literally getting formula rather than the value of formula. Try these: fun.3 - function(formula) { mc - match.call() mc[[1]] - as.name(oneway.test) eval.parent(mc) } fun.3(values ~ group) fun.4 - function(formula) { do.call(oneway.test, list(formula)) } fun.4(values ~ group) On 1/9/07, Adrian Dusa [EMAIL PROTECTED] wrote: Hi all, I want to write a wrapper for an analysis of variance and I face a curious problem. Here are two different wrappers: fun.1 - function(formula) { summary(aov(formula)) } fun.2 - function(formula) { oneway.test(formula) } values - c(15, 8, 17, 7, 26, 12, 8, 11, 16, 9, 16, 24, 20, 19, 9, 17, 11, 8, 15, 6, 14) group - rep(1:3, each=7) # While the first wrapper works just fine: fun.1(values ~ group) # the second throws an error: fun.2(values ~ group) Error in substitute(formula)[[2]] : object is not subsettable ### I also tried binding the two vectors in a data.frame, with no avail. I did find a hack, creating two new vectors inside the function and creating a fresh formula, so I presume this has something to do with environments. Could anybody give me a hint on this? Thank you, Adrian -- Adrian Dusa Romanian Social Data Archive 1, Schitu Magureanu Bd 050025 Bucharest sector 5 Romania Tel./Fax: +40 21 3126618 \ +40 21 3120210 / int.101 __ R-help@stat.math.ethz.ch mailing list 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. __ R-help@stat.math.ethz.ch mailing list 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.
Re: [R] a question of substitute
On Tuesday 09 January 2007 15:14, Gabor Grothendieck wrote: oneway.test is using substitute on its arguments so its literally getting formula rather than the value of formula. Ah-haa... I understand now. Thanks for the tips, they both work as expected. Best, Adrian Try these: fun.3 - function(formula) { mc - match.call() mc[[1]] - as.name(oneway.test) eval.parent(mc) } fun.3(values ~ group) fun.4 - function(formula) { do.call(oneway.test, list(formula)) } fun.4(values ~ group) On 1/9/07, Adrian Dusa [EMAIL PROTECTED] wrote: Hi all, I want to write a wrapper for an analysis of variance and I face a curious problem. Here are two different wrappers: fun.1 - function(formula) { summary(aov(formula)) } fun.2 - function(formula) { oneway.test(formula) } values - c(15, 8, 17, 7, 26, 12, 8, 11, 16, 9, 16, 24, 20, 19, 9, 17, 11, 8, 15, 6, 14) group - rep(1:3, each=7) # While the first wrapper works just fine: fun.1(values ~ group) # the second throws an error: fun.2(values ~ group) Error in substitute(formula)[[2]] : object is not subsettable ### I also tried binding the two vectors in a data.frame, with no avail. I did find a hack, creating two new vectors inside the function and creating a fresh formula, so I presume this has something to do with environments. Could anybody give me a hint on this? Thank you, Adrian -- Adrian Dusa Romanian Social Data Archive 1, Schitu Magureanu Bd 050025 Bucharest sector 5 Romania Tel./Fax: +40 21 3126618 \ +40 21 3120210 / int.101 __ R-help@stat.math.ethz.ch mailing list 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. -- Adrian Dusa Arhiva Romana de Date Sociale Bd. Schitu Magureanu nr.1 050025 Bucuresti sectorul 5 Romania Tel./Fax: +40 21 3126618 \ +40 21 3120210 / int.101 __ R-help@stat.math.ethz.ch mailing list 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.
Re: [R] a question of substitute
oneway.test expects a literal formula, not a variable containing a formula. The help page says formula: a formula of the form 'lhs ~ rhs' where 'lhs' gives the sample values and 'rhs' the corresponding groups. Furthermore, if you had foo.2 - function() oneway.test(value ~ group) it would still not work, as data: an optional matrix or data frame (or similar: see 'model.frame') containing the variables in the formula 'formula'. By default the variables are taken from 'environment(formula)'. I could show you several complicated workarounds, but why do you want to do this? On Tue, 9 Jan 2007, Adrian Dusa wrote: Hi all, I want to write a wrapper for an analysis of variance and I face a curious problem. Here are two different wrappers: fun.1 - function(formula) { summary(aov(formula)) } fun.2 - function(formula) { oneway.test(formula) } values - c(15, 8, 17, 7, 26, 12, 8, 11, 16, 9, 16, 24, 20, 19, 9, 17, 11, 8, 15, 6, 14) group - rep(1:3, each=7) # While the first wrapper works just fine: fun.1(values ~ group) # the second throws an error: fun.2(values ~ group) Error in substitute(formula)[[2]] : object is not subsettable ### I also tried binding the two vectors in a data.frame, with no avail. I did find a hack, creating two new vectors inside the function and creating a fresh formula, so I presume this has something to do with environments. Could anybody give me a hint on this? Thank you, Adrian -- Brian D. Ripley, [EMAIL PROTECTED] Professor of Applied Statistics, http://www.stats.ox.ac.uk/~ripley/ University of Oxford, Tel: +44 1865 272861 (self) 1 South Parks Road, +44 1865 272866 (PA) Oxford OX1 3TG, UKFax: +44 1865 272595 __ R-help@stat.math.ethz.ch mailing list 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.
Re: [R] a question of substitute
On Tuesday 09 January 2007 15:41, Prof Brian Ripley wrote: oneway.test expects a literal formula, not a variable containing a formula. The help page says formula: a formula of the form 'lhs ~ rhs' where 'lhs' gives the sample values and 'rhs' the corresponding groups. Furthermore, if you had foo.2 - function() oneway.test(value ~ group) it would still not work, as data: an optional matrix or data frame (or similar: see 'model.frame') containing the variables in the formula 'formula'. By default the variables are taken from 'environment(formula)'. I could show you several complicated workarounds, but why do you want to do this? Thank you for your reply. The data argument was exactly the next problem I faced. My workaround involves checking if(missing(data)) then uses different calls to oneway.test(). I am certainly interested in other solutions, this one is indeed limited. I do this for the students in the anova class, checking first the homogeneity of variances with fligner.test(), printing the p.value and based on that changing the var.equal argument in the oneway.test() It's just for convenience, but they do like having it all-in-one. Best regards, Adrian -- Adrian Dusa Romanian Social Data Archive 1, Schitu Magureanu Bd 050025 Bucharest sector 5 Romania Tel./Fax: +40 21 3126618 \ +40 21 3120210 / int.101 __ R-help@stat.math.ethz.ch mailing list 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.