[R] How to pass selection criteria in a function
David Winsemius
dwinsemius at comcast.net
Wed Dec 1 19:56:43 CET 2010
On Dec 1, 2010, at 1:12 PM, Charles C. Berry wrote:
> On Wed, 1 Dec 2010, CMcCarthy at bmcc.cuny.edu wrote:
>
>> Hi,
>> Suppose I have the following data
>>
>> name score
>> Abel 88
>> Baker 54
>> Charlie 77
>>
>> stored a table called myData.
>>
>>
>> I want to write a function that will create a table which is a
>> subset of myData containing those have a score > 75.
>>
>> I know I can do this with the following command:
>> subset(myData, score > 75)
>>
>> But I would like to do this via a function, something like:
>>
>> newTable <- function( data, criteria){
>> subset( data, criteria) }
>>
>> and then calling: newTable(myData, score > 75)
>>
>> But this doesn't work. I am sure there is a simple way to do this,
>> but I am stuck! Please help. Thanks!
>
> Simple? Maybe not so much!
>
> You are trying to pass objects without evaluating them. subset is
> rather special in the way it works. Here is one way:
>
>> foo <- function(x,...){
> + mc <- match.call()
> + mc[[1]] <- as.name("subset")
> + eval(mc)
> + }
>> foo(iris, Petal.Width>2.4 )
> Sepal.Length Sepal.Width Petal.Length Petal.Width Species
> 101 6.3 3.3 6.0 2.5 virginica
> 110 7.2 3.6 6.1 2.5 virginica
> 145 6.7 3.3 5.7 2.5 virginica
I've never really understood how to use browser() to develop or
resolve problems with function definitions. Chuck's comments pointing
to the subset function offered another opportunity to teach myself
something new. Here's the console transcript:
> newTable <- function( data, criteria){ crit <-
substitute(criteria);browser()}
# Obviously not a complete function
> newT <- newTable(myData, score < 75)
Called from: newTable(myData, score < 75) #so far so good
Browse[1]> criteria # I realize now that this should
have been "crit"
Error: object 'score' not found # took another look at subset()
code
Browse[1]> newTable <- function( data, criteria){ crit <-
substitute(criteria); logvec <- eval(crit, data, parent.frame());
browser()}
Browse[1]> criteria # still didn't catch on that "crit"
was the local object to examine
Error: object 'score' not found # just slow I guess.
In addition: Warning message:
restarting interrupted promise evaluation
Browse[1]> c # was worried the the redefinition might not take
effect at the top-level
# Try # 2
> newTable <- function( data, criteria){ crit <-
substitute(criteria); logvec <- eval(crit, data, parent.frame());
browser()}
> newT <- newTable(myData, score < 75)
Called from: newTable(myData, score < 75)
Browse[1]> logvec
[1] FALSE TRUE FALSE # now we're getting results
Browse[1]> return(data[logvec, ]) # see if the naive next step works
> newT
name score
2 Baker 54 # very promising
> newTable <- function( data, criteria){ crit <-
substitute(criteria); logvec <- eval(crit, data, parent.frame());
return(data[logvec, ])}
> newT <- newTable(myData, score < 75)
> newT # SUCCESS
name score
2 Baker 54
There is not much in the way of error checking, but it seems to be a
reasonable start (and looks to offer an example, albeit with a some
newbie errors, of an extremely useful R tool.)
>
> Reading the code at the top of lm shows how this kind of strategy
> can be used.
>>
>
> Charles C. Berry Dept of Family/
> Preventive Medicine
Thanks, Chuck.
--
David Winsemius, MD
West Hartford, CT
More information about the R-help
mailing list