Pitt, Joel
2009-Aug-13 20:48 UTC
[R] Coding problem: How can I extract substring of function call within the function
In order to ease my students into the R environment I am developing a package which installs a variety of utility functions as well as slightly modified versions of some standard R functions -- e.g. mean, hist, barplot, .... In my versions of these standard R functions I either add options or alter some defaults that seem to create difficulties for most of my students -- for example, when they do barcharts for two dimensional tables they generally want the bars to be side-by-side and stumble over the standard default of besides=F, and my version of mean by default reports a mean value in the presence of NA's after warning of that presence (but retains the option of setting na.rm=F). (I don't doubt that some (if not many) of you will doubt the wisdom of this, and I would be happy to discuss this in more detail on other occasions.) You might want to think of my replacement R functions as a kind of "training wheels" for R, and, in the spirit of training wheels I include a function in my package that allows a user to revert to the standard version of one or all functions without unloading the package (and loosing its additional functionality). However, I want to add a function that allows a user to revert to running the standard R version of a given function on a one-off basis and that's where my problem comes up. I believe that it should be possible to write a function rStd with the usage rStd(x,...) where x is a function -- e.g. mean, hist, barchart, and the remaining parameters would be any of the parameters that should be passed to the unmodified version of mean, hist, barchart... The problem I have is how to get ahold of that collection of parameters as a single character string. Now I know that sys.calls()[[1]] will give me the full text of the initial call, but the problem is to detach the ... above from that as a text string. If I could do that I'd be done. Here's the incomplete code with comments -- see the gap set off by astericks. rStd=function(x,...){ if(missing(x)) # must have a specified function { cat("Error: No function specified\n"); return(invisible(NULL)); } z=as.character(substitute(x)); # must include code here to check that z is the name # of one of our altered functions # if z is an altered function, e.g., "mean" # then concatenating "x" with z gives the overlaid # function -- e.g. xmean is the standard mean #*************************************************************************** # Now we need to get a hold of the ... text * # * w=sys.calls()[[1]]; # this gets me the whole text of the call * # * # and now here's where the problem arises * # how to I get the ... text if I could get it and say * # assign it to the variable params * # I could then set * # * cmd=sprintf("x%s(%s)",z,params) # see remarks above about z # and then it's done.... eval(parse(text=cmd),sys.frame()); } Any help would be much appreciated. Regards Joel Joel Pitt, Ph.D. Associate Professor & Chair Mathematics & Computer Science Georgian Court University 900 Lakewood Avenue Lakewood, NJ 08540 732-987-2322 [[alternative HTML version deleted]]
Erik Iverson
2009-Aug-13 20:59 UTC
[R] Coding problem: How can I extract substring of function call within the function
Are you sure you just don't want to tell them about the :: operator? It sounds easier than what you're proposing. E.g., base::mean(c(1:10, NA)) -----Original Message----- From: r-help-bounces at r-project.org [mailto:r-help-bounces at r-project.org] On Behalf Of Pitt, Joel Sent: Thursday, August 13, 2009 3:48 PM To: r-help at r-project.org Subject: [R] Coding problem: How can I extract substring of function call within the function In order to ease my students into the R environment I am developing a package which installs a variety of utility functions as well as slightly modified versions of some standard R functions -- e.g. mean, hist, barplot, .... In my versions of these standard R functions I either add options or alter some defaults that seem to create difficulties for most of my students -- for example, when they do barcharts for two dimensional tables they generally want the bars to be side-by-side and stumble over the standard default of besides=F, and my version of mean by default reports a mean value in the presence of NA's after warning of that presence (but retains the option of setting na.rm=F). (I don't doubt that some (if not many) of you will doubt the wisdom of this, and I would be happy to discuss this in more detail on other occasions.) You might want to think of my replacement R functions as a kind of "training wheels" for R, and, in the spirit of training wheels I include a funct! ion in my package that allows a user to revert to the standard version of one or all functions without unloading the package (and loosing its additional functionality). However, I want to add a function that allows a user to revert to running the standard R version of a given function on a one-off basis and that's where my problem comes up. I believe that it should be possible to write a function rStd with the usage rStd(x,...) where x is a function -- e.g. mean, hist, barchart, and the remaining parameters would be any of the parameters that should be passed to the unmodified version of mean, hist, barchart... The problem I have is how to get ahold of that collection of parameters as a single character string. Now I know that sys.calls()[[1]] will give me the full text of the initial call, but the problem is to detach the ... above from that as a text string. If I could do that I'd be done. Here's the incomplete code with comments -- see the gap set off by astericks. rStd=function(x,...){ if(missing(x)) # must have a specified function { cat("Error: No function specified\n"); return(invisible(NULL)); } z=as.character(substitute(x)); # must include code here to check that z is the name # of one of our altered functions # if z is an altered function, e.g., "mean" # then concatenating "x" with z gives the overlaid # function -- e.g. xmean is the standard mean #*************************************************************************** # Now we need to get a hold of the ... text * # * w=sys.calls()[[1]]; # this gets me the whole text of the call * # * # and now here's where the problem arises * # how to I get the ... text if I could get it and say * # assign it to the variable params * # I could then set * # * cmd=sprintf("x%s(%s)",z,params) # see remarks above about z # and then it's done.... eval(parse(text=cmd),sys.frame()); } Any help would be much appreciated. Regards Joel Joel Pitt, Ph.D. Associate Professor & Chair Mathematics & Computer Science Georgian Court University 900 Lakewood Avenue Lakewood, NJ 08540 732-987-2322 [[alternative HTML version deleted]] ______________________________________________ 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.
Gabor Grothendieck
2009-Aug-13 21:19 UTC
[R] Coding problem: How can I extract substring of function call within the function
The Defaults package can be used to change the defaults of functions and reset them back. There is some question on whether all this is advisable. It will invalidate any books, documentation, examples in the help files that come with R and other resources on R that they might have otherwise used by introducing deliberate differences. Later, to learn standard R it will be harder since they will have to unlearn what they learned. If you really must do this I would suggest using different names, e.g. mean2 or Mean, so its clear one is using non-standard versions. In that case you don't need rStd in the first place. Even better, perhaps a one page cheat sheet of common forms would be better than a package full of trivially and annoyingly changed functions, e.g. mean(x, na.rm = TRUE) # mean of non-missings in x barplot(x, beside = TRUE) # bar chart placing bars beside each other On Thu, Aug 13, 2009 at 4:48 PM, Pitt, Joel<pittj at georgian.edu> wrote:> In order to ease my students into the R environment I am developing a package which installs a variety of utility functions as well as slightly modified versions of some standard R functions -- e.g. mean, hist, barplot, .... In my versions of these standard R functions I either add options or alter some defaults that seem to create difficulties for most of my students -- for example, when they do barcharts for two dimensional tables they generally want the bars to be side-by-side and stumble over the standard default of besides=F, and my version of mean by default reports a mean value in the presence of NA's after warning of that presence (but retains the option of setting na.rm=F). (I don't doubt that some (if not many) of you will doubt the wisdom of this, and I would be happy to discuss this in more detail on other occasions.) You might want to think of my replacement R functions as a kind of "training wheels" for R, and, in the spirit of training wheels I include a funct! > ?ion in my package that allows a user to revert to the standard version of one or all functions without unloading the package (and loosing its additional functionality). However, I want to add a function that allows a user to revert to running the standard R version of a given function on a one-off basis and that's where my problem comes up. > > I believe that it should be possible to write a function rStd with the usage rStd(x,...) where x is a function -- e.g. mean, hist, barchart, and the remaining parameters would be any of the parameters that should be passed to the unmodified version of mean, hist, barchart... The problem I have is how to get ahold of that collection of parameters as a single character string. Now I know that sys.calls()[[1]] will give me the full text of the initial call, but the problem is to detach the ... above from that as a text string. If I could do that I'd be done. > > Here's the incomplete code with comments -- see the gap set off by astericks. > > ? ?rStd=function(x,...){ > ? ?if(missing(x)) ?# must have a specified function > ? ?{ > ? ? ? cat("Error: No function specified\n"); > ? ? ? return(invisible(NULL)); > ? ?} > ? ?z=as.character(substitute(x)); > ? ?# must include code here to check that z is the name > ? ?# of one of our altered functions > ? ?# if z is an altered function, e.g., "mean" > ? ?# then concatenating "x" with z gives the overlaid > ? ?# function -- e.g. xmean is the standard mean > ? ?#*************************************************************************** > ? ?# Now we need to get a hold of the ... text ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ?* > ? ?# ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? * > ? ?w=sys.calls()[[1]]; ?# this gets me the whole text of the call ? ? ? ? ?* > ? ?# ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? * > ? ?# and now here's where the problem arises ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? * > ? ?# how to I get the ... text if I could get it and say ? ? ? ? ? ? ? ? ? ? ? ? ?* > ? ?# assign it to the variable params ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? * > ? ?# I could then set ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ?* > ? ?# ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? * > ? ?cmd=sprintf("x%s(%s)",z,params) # see remarks above about z > ? # and then it's done.... > ? ?eval(parse(text=cmd),sys.frame()); > } > > > Any help would be much appreciated. > > Regards > Joel > Joel Pitt, Ph.D. > Associate Professor & Chair > Mathematics & Computer Science > Georgian Court University > 900 Lakewood Avenue > Lakewood, NJ 08540 > 732-987-2322 > > ? ? ? ?[[alternative HTML version deleted]] > > ______________________________________________ > 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. >