Brian P
Brian P

Reputation: 1516

Difficulties using `with` inside a function

I am trying to understand how to pass a data frame to an R function. I found an answer to this question on StackOverflow that provides the following demonstration / solution:

Pass a data.frame column name to a function

df <- data.frame(A=1:10, B=2:11, C=3:12)
fun1 <- function(x, column){
  max(x[,column])
}

fun1(df, "B")
fun1(df, c("B","A"))

This makes sense to me, but I don't quit understand the rules for calling data frames within a function. Take the following example:

data(iris)
x.test <- function(df, x){ 
  out <- with(df, mean(x))
  return(out)
}    
x.test(iris, "Sepal.Length")

The output of this is NA, with a warning message. But, if I do the same procedure without the function it seems to work just fine.

with(iris, mean(Sepal.Length))

I'm obviously missing something here -- any help would be greatly appreciated.

Thanks!

Upvotes: 1

Views: 102

Answers (2)

IRTFM
IRTFM

Reputation: 263481

You have been given the correct advice already (which was to use "[" or "[[" rather than with inside functions) but it might also be helpful to ponder why the problem occurred. Inside the with you asked the mean function to return the mean of a character vector, so NA was the result. When you used with at the interactive level, you had no quotes around the character name of the column and if you had you would have gotten the same result:

> with(iris, mean('Sepal.Length'))
[1] NA
Warning message:
In mean.default("Sepal.Length") :
  argument is not numeric or logical: returning NA

If you had used the R get mechanism for "promoting" a character object to return the result of a named object you would actually have succeeded, although with is still generally not recommended for programming use:

x.test <- function(df, x){ 
   out <- with(df, mean( get(x)) )    #  get() retrieves the named object from the workspace
   return(out)
 }    
 x.test(iris, "Sepal.Length")
#[1] 5.843333

See the Details section of the ?with page for warnings about its use in functions.

Upvotes: 1

James King
James King

Reputation: 6365

This will work

data(iris)
x.test <- function(df, x){ 
  out <- mean(df[, x])
  return(out)
}    
x.test(iris, "Sepal.Length")

Your code is trying to take mean("Sepal.Length") which is clearly not what you want.

Upvotes: 0

Related Questions