4

I have a long script that involves data manipulation and estimation. I have it setup to use a set of parameters, though I would like to be able to run this script multiple times with different sets of inputs kind of like a function.

Running the script produces plots and saves estimates to a csv, I am not particularly concerned with the objects it creates.

I would rather not wrap the script in a function as it is meant to be used interactively. How do people go about doing something like this?

I found this for command line arguments : How to pass command-line arguments when source() an R file but still doesn't solve the interactive problem

Community
  • 1
  • 1
  • I'm struggling to understand how making it a function means you can't "use it interactively". – joran Jan 18 '17 at 21:12
  • By interactive I mean sometimes I want to run the script line by line which I could do using browser but it's not optimal... –  Jan 18 '17 at 21:18
  • Then I suggest making it a function and when you want to run it line by line and if you want to run it in chunks set the parameters and run the content of the function chunk by chunk. If you want a browser just put a browser into the function, source it again and run. – Hansi Jan 18 '17 at 22:18

3 Answers3

2

I have dealt with something similar before. Below is the solution I came up with. I basically use list2env to push variables to either the global or function's local environment and I then source the function in the designated environment.

This can be quite useful especially when coupled with exists as shown in the example below which would allow you to keep your script stand-alone.

These two questions may also be of help: Source-ing an .R script within a function and passing a variable through (RODBC) How to pass command-line arguments when source() an R file

# Function ----------------------------------------------------------------
subroutine <- function(file, param = list(), local = TRUE, ...) {
  list2env(param, envir = if (local) environment() else globalenv())
  source(file, local = local, ...)
}


# Example -----------------------------------------------------------------
# Create an example script
tmp <- "test_subroutine.R"
cat("if (!exists('msg')) msg <- 'no argument provided'; print(msg)", file = tmp)

# Example of using exists in the script to keep it stand-alone
subroutine(tmp)

# Evaluate in functions environment
subroutine(tmp, list(msg = "use function's environment"), local = TRUE)
exists("msg", envir = globalenv()) # FALSE

# Evaluate in global environment
subroutine(tmp, list(msg = "use global environment"), local = FALSE)
exists("msg", envir = globalenv()) # TRUE

unlink(tmp)
Community
  • 1
  • 1
Raad
  • 2,675
  • 1
  • 13
  • 26
1

Just to clarify what was alluded to in Hansi's comment, here is one approach to this issue:

Wrap the script into a function, since this will let you go up one level of abstraction if needed, and will also make it easier to call the function whenever it is needed in any other script.

In cases where you want to use the script interactively, you can put a browser() call somewhere in your script. At the point where browser() is called, the function will pause and keep the environment as-is within the function, and you can then step through the function and use R interactively from within the function.

frandude
  • 77
  • 5
-1

In the base package, check ?commandArgs, you can use this to parse out arguments from the command line.

If I have a script, test.R, containing the code:

args <- commandArgs(trailingOnly=TRUE)

for (arg in args){
  print(arg)
}

and I call it from the command line with rscript as follows:

rscript test.R arg1 arg2 arg3

The output is:

[1] "arg1"
[1] "arg2"
[1] "arg3"
Phantom Photon
  • 768
  • 2
  • 10
  • 20