psyguy
psyguy

Reputation: 361

Include a function from external source R in RMarkdown

Suppose I have a functions.R script in which I have defined a few functions:

foo <- function(x) print(x-2)
bar <- function(x) print(x^3)
...

Now I want to include only foo (and not the whole functions.R in a chunk in RMarkdown.

If I wanted all functions to be included, following this answer, I could have done this via:

``` {r, code = readLines("functions.R")}
```

However, I only need foo in the chunk. How can I do it? Thanks in advance.

Upvotes: 2

Views: 1644

Answers (1)

duckmayr
duckmayr

Reputation: 16940

I adapt the approach from this answer to a related question to solve this problem.1

I stored in the file functions.R your two example functions above:

foo <- function(x) print(x-2)
bar <- function(x) print(x^3)

I then create the following R Markdown document:

---
title: "SO Answer"
author: "duckmayr"
date: "7/8/2019"
output: html_document
---

```{r setup, include=FALSE}
knitr::opts_chunk$set(echo = TRUE)
```

We set up a function to source an R script, but only assign to the global environment the functions we want:

```{r source_function}
source_functions <- function(fcn_names, file_name) {
    env <- new.env()
    source(file_name, local = env)
    for ( i in 1:length(fcn_names) ) {
        assign(fcn_names[i], get(fcn_names[i], envir = env), envir = .GlobalEnv)
    }
}
```

Then we can call it to get *only* the function `foo()`:

```{r get_foo}
source_functions("foo", "functions.R")
ls()
```

This will also work for multiple functions:

```{r get_foo_and_bar}
source_functions(c("foo", "bar"), "functions.R")
ls()
```

Which renders as:

enter image description here

We see that in the first call to source_functions(), only the foo() function is added to the global environment, but not the bar() function, which should work to solve your problem. If you wanted multiple functions from functions.R, this will also work as well, as demonstrated in the second call to source_functions().

Update: Showing the Functions' Code

We can edit our source_functions() function to show the code of the functions it sources, like so:

source_functions <- function(fcn_names, file_name) {
    env <- new.env()
    source(file_name, local = env)
    n <- length(fcn_names)
    result <- character(n)
    for ( i in 1:n ) {
        name <- fcn_names[i]
        fcn <- get(name, envir = env)
        code <- capture.output(show(fcn))
        code <- paste(code[-which(grepl("<env", code))], collapse = " ")
        assign(name, fcn, envir = .GlobalEnv)
        result[i] <- paste(name, "<-", code, collapse = " ")
    }
    return(result)
}

Then our document renders as

enter image description here


1 That question and answer (1) was not in the context of R Markdown, and more importantly (2) only demonstrated how to get all functions from an R script (without getting other objects) rather than particular functions.

Upvotes: 3

Related Questions