UseR10085
UseR10085

Reputation: 8176

How to include data aurgument within custom R function?

I want to include data argument within a custom R function. Right now I am using the following function

Ploy <- function(Sepal.Length = Sepal.Length, Sepal.Width = Sepal.Width, 
                 Petal.Width = Petal.Width, Petal.Length = Petal.Length){
  
  #Calculate some derived parameters
  deltak <- (Sepal.Length - Sepal.Width)/390
  ARk <- Petal.Width*2
  
  dat <- cbind.data.frame(deltak, ARk)
  
  #Fitting quadratic model
  mod <- lm(deltak ~ poly(ARk, 2, raw = TRUE))
  
  deltaK0 <- abs(mod$coefficients[[1]])
  
  Ks <- Petal.Length - deltaK0
  
  return(c(`DeltaK0` = deltaK0, `Ks` = Ks))
}

When I am calling the function I have to use iris$ like

Ploy(Sepal.Length = iris$Sepal.Length, Sepal.Width = iris$Sepal.Width, 
     Petal.Width = iris$Petal.Width, Petal.Length = iris$Petal.Length)

I know there is a workaround using with like

with(iris, Ploy(Sepal.Length = Sepal.Length, Sepal.Width = Sepal.Width, 
                Petal.Width = Petal.Width, Petal.Length = Petal.Length))

But I want to have the call for the Ploy function like

Ploy(Sepal.Length = Sepal.Length, Sepal.Width = Sepal.Width, 
     Petal.Width = Petal.Width, Petal.Length = Petal.Length, data = iris)

How can I achieve it?

Update

Taking clue from the answer of @user2554330, I have used the following code

Ploy <- function(data, Sepal.Length = "Sepal.Length", Sepal.Width = "Sepal.Width", 
                 Petal.Width = "Petal.Width", Petal.Length = "Petal.Length"){
  
  Sepal.Length = data[[Sepal.Length]]
  Sepal.Width = data[[Sepal.Width]]
  Petal.Width = data[[Petal.Width]]
  Petal.Length = data[[Petal.Length]]

  #Calculate some derived parameters
  deltak <- (Sepal.Length - Sepal.Width)/390
  ARk <- Petal.Width*2
  
  dat <- cbind.data.frame(deltak, ARk)
  
  #Fitting quadratic model
  mod <- lm(deltak ~ poly(ARk, 2, raw = TRUE))
  
  deltaK0 <- abs(mod$coefficients[[1]])
  
  Ks <- Petal.Length - deltaK0
  
  return(c(`DeltaK0` = deltaK0, `Ks` = Ks))
}

Now the function can be used like

Ploy(Sepal.Length = "Sepal.Length", Sepal.Width = "Sepal.Width", 
     Petal.Width = "Petal.Width", Petal.Length = "Petal.Length", data = iris)

Upvotes: 1

Views: 110

Answers (2)

pepitoenpeligro
pepitoenpeligro

Reputation: 44

You can specify as many parameters (inputs) to your R functions as you like. The problem you encounter is because of how you are calling those parameters (inputs).

An example of a function statement might be as follows:

# Function declaration
Ploy <- function(sepal_lenght,sepal_width, petal_witdh, petal_length, data){
   print(paste("sepal_lenght inside function is ", sepal_lenght))
   print(paste("sepal_width inside function is ", sepal_width))
   print(paste("petal_witdh inside function is ", petal_witdh))
   print(paste("petal_length inside function is ", petal_length))
  print(paste("Aditional data inside function is ", data))
}

# Running your function with concrete values
Ploy(10,20,3.4,66, 'complex object')


An example result would be:

[1] "sepal_lenght inside function is  10"
[1] "sepal_width inside function is  20"
[1] "petal_witdh inside function is  3.4"
[1] "petal_length inside function is  66"
[1] "Aditional data inside function is  complex object"

That said, for your case, you could perform a function like this:

sepal  <- data.frame(
  "length" = 5.1, 
  "width" = 3.5
)

petal  <- data.frame(
  "length" = 1,4, 
  "width" = 0.2
)

# Function declaration
Ploy <- function(sepal, petal, data){
   print(paste("sepal_lenght inside function is ", sepal$length))
   print(paste("sepal_width inside function is ", sepal$width))
   print(paste("petal_witdh inside function is ", petal$length))
   print(paste("petal_length inside function is ", petal$width))
  print(paste("Aditional data inside function is ", data))
}

# Running your function with concrete values, passing sepal and petal objects
Ploy(sepal, petal, 'more complex object')

So you will obtain:

[1] "sepal_lenght inside function is  5.1"
[1] "sepal_width inside function is  3.5"
[1] "petal_witdh inside function is  1"
[1] "petal_length inside function is  0.2"
[1] "Aditional data inside function is  more complex object"

Upvotes: 1

user2554330
user2554330

Reputation: 44877

What you are asking for is "non-standard evaluation": you don't want to evaluate the expression Sepal.Length in the standard way.

I'd advise against doing this. It's very difficult to get it right, so that you don't have weird behavior in some special cases. The tidyverse packages use it, and even though those packages are written by very smart people who have thought about it very carefully, it still has some weird bugs, e.g. handling ... arguments.

Instead, ask your user to specify the column using a string name, e.g. their call looks like

Ploy(col1 = "Sepal.Length", col2 = "Sepal.Width", 
 col3 = "Petal.Width", data = iris)

Then within your function, using entirely standard evaluation, you can refer to those columns as

data[[col1]]
data[[col2]]
data[[col3]]

Upvotes: 4

Related Questions