Michael Friendly
2010-Mar-16 12:26 UTC
[R] function arguments: name of an object vs. call producing the object?
In a function, say foo.glm for glm objects I want to use the name of the object as a label for some output, but *only* if a glm object was passed as an argument, not a call to glm() producing that object. How can I distinguish these two cases? For example, I can use the following to get the name of the argument: foo.glm <- function(object) { oname <- as.character(sys.call())[2] oname } > indep <- glm(Freq ~ mental + ses, family = poisson, data = Mental) > foo.glm(indep) [1] "indep" But in foo.glm() I want to avoid using this as oname: > foo.glm(glm(formula = Freq ~ mental + ses, family = poisson, data = Mental)) [1] "glm(formula = Freq ~ mental + ses, family = poisson, data = Mental)" Here is Mental, if it matters. dput(Mental) structure(list(ses = structure(c(1L, 1L, 1L, 1L, 2L, 2L, 2L, 2L, 3L, 3L, 3L, 3L, 4L, 4L, 4L, 4L, 5L, 5L, 5L, 5L, 6L, 6L, 6L, 6L), .Label = c("1", "2", "3", "4", "5", "6"), class = c("ordered", "factor")), mental = structure(c(1L, 2L, 3L, 4L, 1L, 2L, 3L, 4L, 1L, 2L, 3L, 4L, 1L, 2L, 3L, 4L, 1L, 2L, 3L, 4L, 1L, 2L, 3L, 4L), .Label = c("Well", "Mild", "Moderate", "Impaired"), class = c("ordered", "factor")), Freq = c(64L, 94L, 58L, 46L, 57L, 94L, 54L, 40L, 57L, 105L, 65L, 60L, 72L, 141L, 77L, 94L, 36L, 97L, 54L, 78L, 21L, 71L, 54L, 71L)), .Names = c("ses", "mental", "Freq"), row.names = c(NA, -24L), class = "data.frame") -- Michael Friendly Email: friendly AT yorku DOT ca Professor, Psychology Dept. York University Voice: 416 736-5115 x66249 Fax: 416 736-5814 4700 Keele Street http://www.math.yorku.ca/SCS/friendly.html Toronto, ONT M3J 1P3 CANADA
Duncan Murdoch
2010-Mar-16 12:44 UTC
[R] function arguments: name of an object vs. call producing the object?
On 16/03/2010 8:26 AM, Michael Friendly wrote:> In a function, say foo.glm for glm objects I want to use the name of the > object as a label for some output, > but *only* if a glm object was passed as an argument, not a call to > glm() producing that object. > How can I distinguish these two cases?Look at typeof(substitute(object)). For example, > f <- function(object) typeof(substitute(object)) > f(aname) [1] "symbol" > f(aname+1) [1] "language" That will tell you if an object was passed by name, or if you got an expression to produce the object. One problem with this approach is that it only looks at the direct call to f, for example > g <- function(x) f(x) > g(aname + 1) [1] "symbol" because substitute looks at the f(x) call, not the g(aname + 1) call. Duncan Murdoch> > For example, I can use the following to get the name of the argument: > > foo.glm <- function(object) { > oname <- as.character(sys.call())[2] > oname > } > > > indep <- glm(Freq ~ mental + ses, family = poisson, data = Mental) > > foo.glm(indep) > [1] "indep" > > But in foo.glm() I want to avoid using this as oname: > > foo.glm(glm(formula = Freq ~ mental + ses, family = poisson, data = > Mental)) > [1] "glm(formula = Freq ~ mental + ses, family = poisson, data = Mental)" > > Here is Mental, if it matters. > > dput(Mental) > structure(list(ses = structure(c(1L, 1L, 1L, 1L, 2L, 2L, 2L, > 2L, 3L, 3L, 3L, 3L, 4L, 4L, 4L, 4L, 5L, 5L, 5L, 5L, 6L, 6L, 6L, > 6L), .Label = c("1", "2", "3", "4", "5", "6"), class = c("ordered", > "factor")), mental = structure(c(1L, 2L, 3L, 4L, 1L, 2L, 3L, > 4L, 1L, 2L, 3L, 4L, 1L, 2L, 3L, 4L, 1L, 2L, 3L, 4L, 1L, 2L, 3L, > 4L), .Label = c("Well", "Mild", "Moderate", "Impaired"), class = > c("ordered", > "factor")), Freq = c(64L, 94L, 58L, 46L, 57L, 94L, 54L, 40L, > 57L, 105L, 65L, 60L, 72L, 141L, 77L, 94L, 36L, 97L, 54L, 78L, > 21L, 71L, 54L, 71L)), .Names = c("ses", "mental", "Freq"), row.names = > c(NA, > -24L), class = "data.frame") >
Michael Friendly
2010-Mar-16 16:16 UTC
[R] function arguments: name of an object vs. call producing the object?
Thanks, Duncan In my context, the following gives me what I want: > foo.glm <- function(object) { + if (typeof(substitute(object))=="symbol") + oname <- as.character(sys.call())[2] + else oname <- NULL + oname + } > > > > indep <- glm(Freq ~ mental + ses, family = poisson, data = Mental) > foo.glm(indep) [1] "indep" > > foo.glm(glm(formula = Freq ~ mental + ses, family = poisson, data = Mental)) NULL > Duncan Murdoch wrote:> On 16/03/2010 8:26 AM, Michael Friendly wrote: >> In a function, say foo.glm for glm objects I want to use the name of >> the object as a label for some output, >> but *only* if a glm object was passed as an argument, not a call to >> glm() producing that object. >> How can I distinguish these two cases? > > Look at typeof(substitute(object)). For example, > > > f <- function(object) typeof(substitute(object)) > > f(aname) > [1] "symbol" > > f(aname+1) > [1] "language" > > That will tell you if an object was passed by name, or if you got an > expression to produce the object. > > One problem with this approach is that it only looks at the direct > call to f, for example > > > g <- function(x) f(x) > > g(aname + 1) > [1] "symbol" > > because substitute looks at the f(x) call, not the g(aname + 1) call. > > Duncan Murdoch > > >> >> For example, I can use the following to get the name of the argument: >> >> foo.glm <- function(object) { >> oname <- as.character(sys.call())[2] >> oname >> } >> >> > indep <- glm(Freq ~ mental + ses, family = poisson, data = Mental) >> > foo.glm(indep) >> [1] "indep" >> >> But in foo.glm() I want to avoid using this as oname: >> > foo.glm(glm(formula = Freq ~ mental + ses, family = poisson, data >> = Mental)) >> [1] "glm(formula = Freq ~ mental + ses, family = poisson, data = >> Mental)" >> >> Here is Mental, if it matters. >> >> dput(Mental) >> structure(list(ses = structure(c(1L, 1L, 1L, 1L, 2L, 2L, 2L, >> 2L, 3L, 3L, 3L, 3L, 4L, 4L, 4L, 4L, 5L, 5L, 5L, 5L, 6L, 6L, 6L, >> 6L), .Label = c("1", "2", "3", "4", "5", "6"), class = c("ordered", >> "factor")), mental = structure(c(1L, 2L, 3L, 4L, 1L, 2L, 3L, >> 4L, 1L, 2L, 3L, 4L, 1L, 2L, 3L, 4L, 1L, 2L, 3L, 4L, 1L, 2L, 3L, >> 4L), .Label = c("Well", "Mild", "Moderate", "Impaired"), class = >> c("ordered", >> "factor")), Freq = c(64L, 94L, 58L, 46L, 57L, 94L, 54L, 40L, >> 57L, 105L, 65L, 60L, 72L, 141L, 77L, 94L, 36L, 97L, 54L, 78L, >> 21L, 71L, 54L, 71L)), .Names = c("ses", "mental", "Freq"), row.names >> = c(NA, >> -24L), class = "data.frame") >> >-- Michael Friendly Email: friendly AT yorku DOT ca Professor, Psychology Dept. York University Voice: 416 736-5115 x66249 Fax: 416 736-5814 4700 Keele Street http://www.math.yorku.ca/SCS/friendly.html Toronto, ONT M3J 1P3 CANADA
Bert Gunter
2010-Mar-16 16:18 UTC
[R] function arguments: name of an object vs. call producing theobject?
Michael: Well, several possibilities come to mind, but their appropriateness depends on what your argument could be. 1) The deparse(substitute(...)) construction will get you the character string that was used as the argument and you can grep for "~" in it. 2) Or maybe check the class of the argument (e.g. if it's a formula it will inherit from "formula"). 3) Or create separate (S3) methods foo.glm, foo.formula, etc. for the different classes that you wish to consider. This might be the cleanest approach, but it requires more planning. HTH Bert Gunter Genentech Nonclinical Biostatistics -----Original Message----- From: r-help-bounces at r-project.org [mailto:r-help-bounces at r-project.org] On Behalf Of Michael Friendly Sent: Tuesday, March 16, 2010 5:27 AM To: R-Help Subject: [R] function arguments: name of an object vs. call producing theobject? In a function, say foo.glm for glm objects I want to use the name of the object as a label for some output, but *only* if a glm object was passed as an argument, not a call to glm() producing that object. How can I distinguish these two cases? For example, I can use the following to get the name of the argument: foo.glm <- function(object) { oname <- as.character(sys.call())[2] oname } > indep <- glm(Freq ~ mental + ses, family = poisson, data = Mental) > foo.glm(indep) [1] "indep" But in foo.glm() I want to avoid using this as oname: > foo.glm(glm(formula = Freq ~ mental + ses, family = poisson, data = Mental)) [1] "glm(formula = Freq ~ mental + ses, family = poisson, data = Mental)" Here is Mental, if it matters. dput(Mental) structure(list(ses = structure(c(1L, 1L, 1L, 1L, 2L, 2L, 2L, 2L, 3L, 3L, 3L, 3L, 4L, 4L, 4L, 4L, 5L, 5L, 5L, 5L, 6L, 6L, 6L, 6L), .Label = c("1", "2", "3", "4", "5", "6"), class = c("ordered", "factor")), mental = structure(c(1L, 2L, 3L, 4L, 1L, 2L, 3L, 4L, 1L, 2L, 3L, 4L, 1L, 2L, 3L, 4L, 1L, 2L, 3L, 4L, 1L, 2L, 3L, 4L), .Label = c("Well", "Mild", "Moderate", "Impaired"), class = c("ordered", "factor")), Freq = c(64L, 94L, 58L, 46L, 57L, 94L, 54L, 40L, 57L, 105L, 65L, 60L, 72L, 141L, 77L, 94L, 36L, 97L, 54L, 78L, 21L, 71L, 54L, 71L)), .Names = c("ses", "mental", "Freq"), row.names = c(NA, -24L), class = "data.frame") -- Michael Friendly Email: friendly AT yorku DOT ca Professor, Psychology Dept. York University Voice: 416 736-5115 x66249 Fax: 416 736-5814 4700 Keele Street http://www.math.yorku.ca/SCS/friendly.html Toronto, ONT M3J 1P3 CANADA ______________________________________________ R-help at r-project.org 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.