19  Function within Function

19.1 Function: Mean (AM, GM, HM)

  • Calculate AM, GM and HM of a numeric vector using the following formula.

Arithmetic Mean (AM)

\[ \large AM = (x_1 + x_2 + ... + x_n)/n = \frac{1}{n}\sum\limits_{i=1}^{n} x_{i}\]

Geometric Mean (GM)

\[ \large GM = \sqrt[n]{(x_1 x_2 ... x_n)} = \left( \prod \limits_{i=1}^{n} x_{i} \right) ^{\frac{1}{n}} \]

Harmonic Mean (HM)

\[ \large HM = \frac{n}{(\frac{1}{x_1} + \frac{1}{x_2} + ... + \frac{1}{x_n})} = \frac{1}{\frac{1}{n}\sum\limits_{i=1}^{n} \frac{1}{x_i}}\]

19.2 Functions within a function

Note: The following script is for demonstration purpose only explaining the structure of a function and calling a function within a function.

We are expanding all base functions without any obvious advantages here. A possible optimal version is shown in the next section.

Code
fn_Mean = function(x, ...) {

    fn_n = function(x, na.rm = FALSE) ifelse(na.rm, length(na.omit(x)), length(x))
    n = fn_n(x, ...)

    fn_sum = function(x, ...) sum(x, ...)

    fn_prod = function(x, ...) prod(x, ...)

    fn_suminv = function(x, ...) sum(1/x, ...)

    fn_AM = function(x, ...) {
        out = fn_sum(x, ...)/fn_n(x, ...)
        return(out)
    }

    fn_GM = function(x, ...) {
        out = fn_prod(x, ...)^(1/fn_n(x, ...))
        return(out)
    }

    fn_HM = function(x, ...) {
        out = fn_n(x, ...)/fn_suminv(x, ...)
        return(out)
    }

    AM = fn_AM(x, ...)
    GM = fn_GM(x, ...)
    HM = fn_HM(x, ...)

    Mean = list(n = n, AM = AM, GM = GM, HM = HM)

    return(Mean)

}

19.3 Data

Code
A = c(11, 12, 15, 14, 18)

B = c(NA, 12, 15, 14, 18)

19.4 Function call 1

Code
A_mean = fn_Mean(A)

A_mean
$n
[1] 5

$AM
[1] 14

$GM
[1] 13.79155

$HM
[1] 13.5909

19.5 Function call 2

Code
B_mean = fn_Mean(B, na.rm = TRUE)

B_mean
$n
[1] 4

$AM
[1] 14.75

$GM
[1] 14.5938

$HM
[1] 14.44126

19.6 Optimal version

We have all base functions available; a possible optimal version of the above function can be written as shown below.

Code
Mean = function(x, ...) {
    fn_n = function(x, na.rm = FALSE) ifelse(na.rm, length(na.omit(x)), length(x))
    n = fn_n(x, ...)
    AM = mean(x, ...)
    GM = exp(mean(log(x), ...))
    HM = 1/mean(1/x, ...)
    Mean = list(n = n, AM = AM, GM = GM, HM = HM)
    return(Mean)
}

19.7 Function call 1

Code
A_mean = Mean(A)

A_mean
$n
[1] 5

$AM
[1] 14

$GM
[1] 13.79155

$HM
[1] 13.5909

19.8 Function call 2

Code
B_mean = Mean(B, na.rm = TRUE)

B_mean
$n
[1] 4

$AM
[1] 14.75

$GM
[1] 14.5938

$HM
[1] 14.44126