Generic Functions in R

The generic functions in R Language are objects that determine how the function will treat it. A generic function performs an action (or task) on its arguments specific to the class of the argument itself. A default action will be performed if an argument lacks any class attribute; that is, if an argument of the function has a class not catered for specifically by the generic function, a default action will be provided.

The class mechanism in R provides the facility of designing and writing generic functions in R for special purposes. For example, the generic functions in R such as

  • the plot() is used for displaying objects graphically,
  • the summary() is used for summarizing analyses of various types of objects
  • the anova() is used for comparing different statistical models
  • the print() is used to display the results of various types of objects

The Generic Functions in R can handle a large number of classes. For example, the function plot() has a default method and variants for different types of objects, such as data.frame, density, factor, and many more. A complete list of Generic Functions in R can be obtained by using

methods(plot)
methods(summary)
Generic Functions in R language

The body of a Generic function in R is concise and short. For example,

print

## Output
function (x, ...) 
UseMethod("print")
<bytecode: 0x0000029448a0aa40>
<environment: namespace:base>

From the above code, the body of the Generic Function UseMethod indicates that this is a generic function.

Key Concepts and Characteristics

The following are key concepts and characteristics of generic functions in R.

  • Dispatch: When an object is passed to a generic function, R determines the appropriate method to execute based on the class of the object provided. This process is known as dispatch.
  • Methods: A method is a specific implementation of a generic function for a particular class of the object. It provides instructions on how the function should behave when applied to certain objects of that class.
  • Class Inheritance: R supports class inheritance, allowing methods defined for a parent class to be inherited by its child classes. This enables generic functions to work seamlessly with objects from different classes within a hierarchy.
  • Default Methods: If no method is defined for a specific class, R will look for a default method. The default method is typically defined for the generic function’s base class or a more generic class.

Benefits of Generic Functions in R

The following are some benefits of using and creating generic functions in R

  • Code Reusability: Generic functions can be used with different types of objects, reducing the need for redundant code.
  • Readability: Generic functions can improve code readability by separating the generic interface from the specific implementations.
  • Polymorphism: Generic functions allow the user to write code that can work with objects of different classes, promoting flexibility and adaptability.
  • Extensibility: New methods can be added for custom classes, making it easy to extend the functionality of generic functions.

Best Practices for Creating Generic Functions in R Language

For creating or writing generic functions, the following are the best practices to follow:

  • Give clear and descriptive names to generic functions and their methods.
  • Define methods for commonly used classes to ensure compatibility.
  • Consider using inheritance to avoid redundant code in methods for related classes.
  • Test the generic functions thoroughly to ensure they work as expected with different types of objects.

Example of Creating Generic Functions

To create/write generic functions in R, define a function with the desired name and arguments. One can then define methods for different classes using the UseMethod function within the body of a generic function. Consider the following example

gf <- function(x) {
  UseMethod("gf")
}

gf.numeric <- function(x) {
  # Method for numeric objects
  mean(x)
}

gf.character <- function(x) {
  # Method for character objects
  nchar(x)
}

In the above exemplary code, gf() is defined as a generic function. The UseMethod() function tells R to dispatch the call to the appropriate method based on the class of the argument x. The gf.numeric and gf.character methods provide specific implementations for numeric and character objects, respectively. Let us check the behaviour of the fg() function created as a generic function

x <- 1:5  # Numeric Vector

gf(x)

## Output
[1] 3

gf("statistics")

## Output
[1] 10

Learn about how to get or view the source code of a function or method.

Frequently Asked Questions About R, Generic Functions in R

https://itfeature.com, https://gmstat.com

Learn How to Create User Defined Functions in R

Introduction to User Defined Functions in R

One can create user defined functions in R Language easily. User-defined functions allow to write/create custom blocks of code to be reused throughout the analysis. The article presents some useful examples of how to write user defined functions in R Language. R language helps to create much more efficient and possibly elegant coding.

Assigning Function to a Variable

Example 1: Create a simple function and assign the function to a variable name as we do with any other objects.

f <- function(x, y = 0){
		z <- x + y
		z
}

x = rnorm(10)
f(x + y)

Regression Coefficients

Example 2: Given $n\times 1$ vector of $y$ and matrix of $X$ the $\hat{\beta}=E[X|y] = (X’X)^{-1}X’y$, where $(X’X)^{-1}$ is generalized invers of $X’X$.

Beta <- function(x, y){
		X <- qr(x)
		qr.coef(X, y)
	}

attach(mtcars)
xmat = cbind(1, hp, wt)
yvar = mpg
regcoef <- Beta(xmat, yvar)

The qr() function computes the QR decomposition of a matrix. The QR decomposition if used to solve the equation $Ax=b$ for a given matrix $A$, and vector $b$. It is very useful in computing regression coefficients and in applying Newton Raphson’s algorithm.

User Defined Functions in R

Removing all Objects from globalenv

Example 3: Create a function capable of removing all objects from the globalenv.

clear <- function(env = globalenv() ){
		obj = ls(envir = env)
		rm(list = obj, envir = env)
}

The clear() function removes all objects from a specified environment and seems to work correctly. However, the clear() function detects also itself and as a result, it cannot be reused without redefining the function again.

The clear() function can be improved to keep the function clear() when all other objects are deleted.

clear <- function(env = globalenv()){
		objects <- objects(env)
		objects <- objects[objects != "clear"]
		rm(list = objects, envir = env)
		invisible(NULL)
	}

Computing Measure of Central Tendency

Example 4: Create a function that can compute some basic Measure of Central Tendency.

center = function(x, type){
	switch(type, 
		mean = mean(x),
		median = median(x),
		trimmed = mean(x, trim = 0.1))
}

attach(airquality)
center(Temp, "mean")     # for calcualtion of mean
center(Temp, "median")   # for calculation of median
center(Temp, "trimmed")  # for calculation of trimmed mean
User defined functions in R: Measure of Central Tendency

Note that the user-defined functions in R can incorporate conditional statements, loops, and other functionalities to perform more advanced tasks. They can also have default parameter values for added flexibility.

https://itfeature.com

https://gmstat.com

Components of Functions in R Language

Components of Function in R Language

Functions in the R Language are objects with three basic components. The components of functions in R language are:

Let us discuss the components of functions in R language in detail.

Formal Argument in R

To learn about Formal argument in R language, see the post formal argument, also see the basics about functions in R Language.

Body of a Function

The body of a function is parsed R statements. The body of a function is usually a collection of statements in braces but it can be a single statement, a symbol, or even a constant.

Environment of a Function

The environment of a function is the environment that was active at the time that the function was created. The environment of a function is a structural component of the function and belongs to the function itself.

A fourth component of a function in R language can be considered as a “Return Value” by a function.

Return Value of a Function

The last object called within a function is returned by the function and therefore available for assignment. Functions can return only a single value but in practice, this is not a limitation as a list containing any number of objects can be returned. Objects can be returned visible or invisible. This option does not affect the assignment side but affects the way results are displayed when the function is called.

y <- function(n){
  out <- runif(n)
  cat (head(out))
  invisible(out)
}

Functions Closures in R

A function closure or closure is a function together with a referencing environment. Almost all functions in R are closures as they remember the environment where they were created. The functions that cannot be classified as closures, and therefore do not have a referencing environment, are known as primitives.

In R, internal functions are called the underlying C code. These sum() and c() are good cases in point:

environment(sum)

When we call a function, a new environment is created to hold the function’s execution, and normally, that environment is destroyed when the function exists. But, if we define a function g() that returns a f(), the environment where f() is created is the execution environment of g(), that is, the execution environment of g() is the referencing environment of f(). As a consequence, the execution environment of g() is not destroyed as g() exists but it persists as long as f() exists. Finally as f() remembers all objects bound to its referencing environment f() remembers all objects bound to the execution environment of g().

We can use the referencing environment of f(), to hold any of the objects and these will be available to f().

g <- function(){
  y <- 1
  function(x){
    x + y
  }
  
f1 <- g()
  
print(f1)
  
f1(3)
components of Functions in R Language

Closures can be used to write functions that in turn closures can be used to generate new functions. This allows us to have a double layer of development: a first layer that is used to do all the complex work in common to all functions and a second layer that defines the details of each function.

f <- function(i){
  function(x){
    x+i
  }
}
f1 <- f(1)
f2 <- f(2)
f2(4)
Functions in R Language

By understanding these components, one can effectively create and use functions to enhance one’s R programming.

Note that in R language:

  • Functions can be nested within other functions.
  • Functions can access variables from the environment where they are defined (lexical scoping).
  • R provides many built-in functions for various tasks.
  • One can create customized functions to automate repetitive tasks and improve code readability.

https://itfeature.com

https://rfaqs.com

https://gmstat.com