Passing argument to subset() and unique() - r

I am using the phyloseq package.
test <- function( ...){
bar <- unique(sampleData[,'pH'])
foo <- subset_samples(phyloseqObject, pH == as.numeric(bar[1]#.Data))
print(foo)
}
test(pH)
I want to pass pH as an argument to test() but unique() won't accept it as valid. I can pass 'pH' to test() but subset_samples() won't accept that as valid. I have tried coercing the argument to several different types with no luck.
SORCE for subset_samples:
subset_samples <- function(physeq, ...){
if( is.null(sample_data(physeq)) ){
cat("Nothing subset. No sample_data in physeq.\n")
return(physeq)
} else {
oldDF <- as(sample_data(physeq), "data.frame")
newDF <- subset(oldDF, ...)
if( class(physeq) == "sample_data" ){
return(sample_data(newDF))
} else {
sample_data(physeq) <- sample_data(newDF)
return(physeq)
}
}
}

Try this instead:
test=function(x,...){
bar=unique(mtcars[,x])
foo=subset(mtcars,mtcars[,x]==bar[1])
return(foo)
}

Building on what #desc said I managed to solve it like this:
test <- function(...){
bar <- unique(sampleData[,...])
foo <- subset_samples(phyloseqObject, eval(parse(bar#names)) == as.numeric(bar[1]))
print(foo)
}
test('pH')

Related

Generic function for NA type

I want to make a special behavour for function when an argument b is NA. I don't want to do this with if so I prefer generic. This is my try:
foo <- function(x) {
UseMethod("foo", x)
}
foo.numeric <- function(x) {
print("numeric")
}
foo.default <- function(x) {
print("def")
}
foo.NA <- function(x) {
print("na")
}
now when I run foo(NA) i want to run foo.NA() but foo.default() is executed.

call a function from a vector of given functions in R

have the following function:
setTypes <- function(df2, ...) {
fns <- as.list(substitute(list(...)))
for(i in 1:length(df2)) {
if(fns[i] == '') {
next
}
df2[i,] <- fns[i](df2[i,])
}
return(df2)
}
want to do this:
test<-setTypes(sls,c('','as.Date','','','as.numeric','as.numeric'))
idea is to change the types of the fields in a data frame without having to do sls$field <- as.numeric(sls$field) for every field.
I had written a function like this that worked:
fn <- function(t) {
return(t("55.55000"))
}
and the output is this:
> fn(as.numeric)
[1] 55.55
however, i can't figure out why either doing variable length argument as a list and calling it as list[index](input) doesn't work. or even passing a vector of functions like c(as.Date, as.numeric, as.character) and doing c[1]('2015-10-10') # as.Date('2015-10-10')
I am receiving the error 'attempt to apply non-function'.. I've also tried using call but to no avail. Help?
The problem is that class(c[1]) is a list use c[[1]] instead
Example code
v <- c(as.numeric,as.character)
v[[1]]("1")
v[[2]](1)
EDIT
Your example should be:
setTypes <- function(df2, ...) {
fns <- list(...)
for(i in 1:NCOL(df2)) {
if(is.function(fns[[i]])) {
df2[,i] <- fns[[i]](df2[,i])
}
}
return(df2)
}
df <- data.frame(v1 = c(1,2), v2 = c("1","2"))
setTypes(df,as.character,'',as.numeric)

R - Subsetting subsets of variable names in loops

Q: How do I subset a subset of a changing variable inside a function or loop?
Assume I have the following code for determining regression stats for multiple data sets :
dat1 <- data.frame(col1=1:5,col2=6:10)
dat2 <- data.frame(col1=11:15,col2=16:20)
func <- function(data,col.no){
get(data)[,col.no]
}
for(i in c('dat1','dat2')) {
mod.name <- paste0('fit.',i)
assign(mod.name,lm(get(i)[,1]~get(i)[,2]),envir = .GlobalEnv)
}
mod.pvals <- NULL
p.func <- function(attr.name) {
for(i in c('dat1','dat2')) {
mod.name <- paste0('fit.',i)
p.val <- summary(get(mod.name))[attr.name]
mod.pvals <- c(mod.pvals,p.val)
}
mod.pvals
}
r.vals <- p.func('r.squared')
adj.r.vals <- p.func('adj.r.squared')
coef.vals <- p.func('coefficients')
This works just fine with 'r.squared','adj.r.squared',etc.
But I want to access the p-value of the model in the same function.
Outside of a function I'd choose:
summary(fit)$coefficients[2,4]
But how do I do this inside of the function??
I unsuccessfully tried:
summary(get(mod.name))['coefficients'][2,4]
Error in summary(get(mod.name))["coefficients"][[2, 4]] :
incorrect number of subscripts
So then I thought about just changing my code for p.val in the function above:
p.val <- paste0('summary(',mod.name ,')$',attr.name)
get(p.val)
But when I run the code I get the following error:
p.vals <- p.func('coefficients[2,4]')
Error in get(p.val) :
object 'summary(fit.dat1)$coefficients[2,4]' not found
I guess get() doesn't work like this. Is there a function that I can replace get() with?
Other thoughts on how I could make this work??
One solution is to use eval() and parse():
p.val <- eval(parse(text=paste0("summary(",mod.name,")[",paste0(attr.name),"]")))
So the function would be:
mod.pvals <- NULL
p.func <- function(attr.name) {
for(i in c('dat1','dat2')) {
mod.name <- paste0('fit.',i)
p.val <- eval(parse(text=paste0("summary(",mod.name,")[",attr.name,"]")))
mod.pvals <- c(mod.pvals,p.val)
}
mod.pvals
}
r.vals <- p.func(attr.name = '\'r.squared\'')
p.vals <- p.func(attr.name = '[\'coefficients\']][2,4')

R - Detecting expressions

What type of object is passed to myFunc as x? It doesn't seem to be an expression, nor a function and str just evaluates it. I understand that I can use force() to evaluate. I'm wondering if there's some way to gather more information about x without evaluating it.
myFunc = function( x )
{
is.expression( x )
is.function( x )
str( x )
}
myFunc( { x = 5; print( x + 1 ) } )
You can use match.call for extracting the arguments:
myFunc <- function( x ) {
x <- match.call()$x
print(class(x))
print(typeof(x))
print(mode(x))
print(storage.mode(x))
print(is.expression(x))
print(is.call(x))
if (is.call(x)) print(x[[1]])
}
myFunc({x = 5; print("a")})
myFunc(expression(x))
x <- factor(1)
myFunc(x)
myFunc(1)
Probably I need to say that { is a function in R, so {...} is no more than call.
Updated: why x is not function while { is function:
f <- function(x) {
x <- match.call()$x
print(eval(x[[1]]))
print(is.function(eval(x[[1]])))
}
f({1})
I think class would do the trick... See docs.
EDIT: According to the docs,
for {, the result of the last expression evaluated
Which means the class is the class resulting from the evaluation, which is why it not showing up as an "expression". It is being passed after evaluation.
Dason just posted a similar response to this on Talkstats.com for determining if an object is a data frame or a list (click here for a link to that post). I just extended it to an expression which I think suits your needs.
j.list <- function(list, by = NULL){
print("list")
print(list)
}
j.data.frame <- function(df, ..., by = NULL){
print("data frame")
print(df)
}
j.expression <- function(expression, by = NULL){
print("expression")
print(expression)
}
j <- function(x, ...){
UseMethod("j")
}
j(list(test = "this is a list"))
j(data.frame(test = 1:10))
j(expression(1+ 0:9))

How to bind function arguments

How do I partially bind/apply arguments to a function in R?
This is how far I got, then I realized that this approach doesn't work...
bind <- function(fun,...)
{
argNames <- names(formals(fun))
bindedArgs <- list(...)
bindedNames <- names(bindedArgs)
function(argNames[!argNames %in% bindedArgs])
{
#TODO
}
}
Thanks!
Here's a version of Curry that both preserves lazy evaluation of function argument, but constructs a function that prints moderately nicely:
Curry <- function(FUN, ...) {
args <- match.call(expand.dots = FALSE)$...
args$... <- as.name("...")
env <- new.env(parent = parent.frame())
if (is.name(FUN)) {
fname <- FUN
} else if (is.character(FUN)) {
fname <- as.name(FUN)
} else if (is.function(FUN)){
fname <- as.name("FUN")
env$FUN <- FUN
} else {
stop("FUN not function or name of function")
}
curry_call <- as.call(c(list(fname), args))
f <- eval(call("function", as.pairlist(alist(... = )), curry_call))
environment(f) <- env
f
}
It basically works by generating an anonymous function in exactly the same way you would if you were constructing the partial binding yourself.
Actually, this seems to work as a work around
bind <- function(fun,...)
{
boundArgs <- list(...)
formals(fun)[names(boundArgs)] <- boundArgs
fun
}
However, ideally I want the bound arguments to disappear completely from the new function so that calls to the new function can happen with name specification, e.g. with add <- function(a,b) a+b I would like (bind(add,a=2))(1) to return 3.
Have you tried looking at roxygen's Curry function?
> library(roxygen)
> Curry
function (FUN, ...)
{
.orig = list(...)
function(...) do.call(FUN, c(.orig, list(...)))
}
<environment: namespace:roxygen>
Example usage:
> aplusb <- function(a,b) {
+ a + 2*b
+ }
> oneplusb <- Curry(aplusb,1)
> oneplusb(2)
[1] 5
Edit:
Curry is concisely defined to accept named or unnamed arguments, but partial application of fun to arguments by way of formal() assignment requires more sophisticated matching to emulate the same functionality. For instance:
> bind <- function(fun,...)
+ {
+ argNames <- names(formals(fun))
+ boundArgs <- list(...)
+ boundNames <- names(boundArgs)
+ if(is.null(boundNames)) {
+ formals(fun)[1:length(boundArgs)] <- boundArgs
+ } else {
+ formals(fun)[match(names(boundArgs),argNames)] <- boundArgs
+ }
+ fun
+ }
> oneplusb <- bind(aplusb,1)
> oneplusb(2)
Error in 2 * b : 'b' is missing
Because the first argument in this function is still a, you need to specify which argument 2 is intended for (b=), or pass it as the second argument.
> oneplusb
function (a = 1, b)
{
a + 2 * b
}
> oneplusb(b=2) ## or oneplusb(,2)
[1] 5

Resources