execute functions immediately when opening R - r

I was wondering how I can execute some pre-defined functions when I open R or R-studio?
I know that it sounds silly, but I installed package praise and sort of want to try executing praise() automatically every time I open R or R studio, without actually typing in praise().

For this you can use .First() and .Last() in the .Rprofile.
It's a typical R file, launched on startup and used primarly to export some stuff by default.
Example .Rprofile:
# .First() run at the start of every R session.
# Use to load commonly used packages?
.First <- function() {
library(ggplot2)
cat("\nSuccessfully loaded .Rprofile at", date(), "\n")
}
# .Last() run at the end of the session
.Last <- function() {
cat("\nGoodbye at ", date(), "\n")
}
Related: Expert R users, what's in your .Rprofile?

Related

using rstudioapi in devtools tests

I'm making a package which contains a function that calls rstudioapi::jobRunScript(), and I would like to to be able to write tests for this function that can be run normally by devtools::test(). The package is only intended for use during interactive RStudio sessions.
Here's a minimal reprex:
After calling usethis::create_package() to initialize my package, and then usethis::use_r("rstudio") to create R/rstudio.R, I put:
foo_rstudio <- function(...) {
script.file <- tempfile()
write("print('hello')", file = script.file)
rstudioapi::jobRunScript(
path = script.file,
name = "foo",
importEnv = FALSE,
exportEnv = "R_GlobalEnv"
)
}
I then call use_test() to make an accompanying test file, in which I put:
test_that("foo works", {
foo_rstudio()
})
I then run devtools::test() and get:
I think I understand the basic problem here: devtools runs a separate R session for the tests, and that session doesn't have access to RStudio. I see here that rstudioapi can work inside child R sessions, but seemingly only those "normally launched by RStudio."
I'd really like to use devtools to test my function as I develop it. I suppose I could modify my function to accept an argument passed from the test code which will simply run the job in the R session itself or in some other kind of child R process, instead of an RStudio job, but then I'm not actually testing the normal intended functionality, and if there's an issue which is specific to the rstudioapi::jobRunScript() call and which could occur during normal use, then my tests wouldn't be able to pick it up.
Is there a way to initialize an RStudio process from within a devtools::test() session, or some other solution here?

How to call a parallelized script from command prompt?

I'm running into this issue and I for the life of me can't figure out how to solve it.
Quick summary before example:
I have several hundred data sets from which I want create reports on everyday. In order to do this efficiently, I parallelized the process with doParallel. From within RStudio, the process works fine, but when I try to make the process automatic via Task Scheduler on windows, I can't seem to get it to work.
The process within RStudio is:
I call a script that sources all of my other scripts, each individual script has a header section that performs the appropriate package import, so for instance it would look like:
get_files <- function(){
get_files.create_path() -> path
for(file in path){
if(!(file.info(paste0(path, file))[['isdir']])){
source(paste0(path, file))
}
}
}
get_files.create_path <- function(){
return(<path to directory>)
}
#self call
get_files()
This would be simply "Source on saved" and brings in everything I need into the .GlobalEnv.
From there, I could simply type: parallel_report() which calls a script that sources another script that houses the parallelization of the report generations. There was an issue awhile back with simply calling the parallelization directly (I wonder if this is related?) and so I had to make the doParallel script a non-function housing script and thus couldn't be brought in with the get_files script which would start the report generation every time I brought everything in. Thus, I had to include it in its own script and save it elsewhere to be called when necessary. The parallel_report() function would simply be:
parallel_report <- function(){
source(<path to script>)
}
Then the script that is sourced is the real parallelization script, and would look something like:
doParallel::registerDoParallel(cl = (parallel::detectCores() - 1))
foreach(name = report.list$names,
.packages = c('tidyverse', 'knitr', 'lubridate', 'stringr', 'rmarkdown'),
.export = c('generate_report'),
.errorhandling = 'remove') %dopar% {
tryCatch(expr = {
generate_report(name)
}, error = function(e){
error_handler(error = e, caller = paste0("generate report for ", name, " from parallel"), line = 28)
})
}
doParallel::stopImplicitCluster()
The generate_report function is simply an .Rmd and render() caller:
generate_report <- function(<arguments>){
#stuff
generate_report.render(<arguments>)
#stuff
}
generate_report.render <- function(<arguments>){
rmarkdown::render(
paste0(data.information#location, 'report_generator.Rmd'),
params = list(
name = name,
date = date,
thoughts = thoughts,
auto = auto),
output_file = paste0(str_to_upper(stock), '_report_', str_remove_all(date, '-'))
)
}
So to recap, in RStudio I would simply perform the following:
1 - Source save the script to bring everything
2 - type parallel_report
2.a - this calls directly the doParallization of generate_report
2.b - generate_report calls an .Rmd file that houses the required function calling and whatnot to produce the reports
And the process starts and successfully completes without a hitch.
In order to make the situation automatic via the Task Scheduler, I made a script that the Task Scheduler can call, named automatic_caller:
source(<path to the get_files script>) # this brings in all the scripts and data into the global, just
# as if it were being done manually
tryCatch(
expr = {
parallel_report()
}, error = function(e){
error_handler(error = e, caller = "parallel_report from automatic_callng", line = 39)
})
The error_handler function is just an in-house script used to log errors throughout.
So then on the Task Schedule's tasks I have the Rscript.exe called and then the automatic_caller after that. Everything within the automatic_caller function works except for the report generation.
The process completes almost automatically, and the only output I get is an error:
"pandoc version 1.12.3 or higher is required and was not found (see the help page ?rmarkdown::pandoc_available)."
But rmarkdown is within the .export call of the doParallel and it is in the scripts that use it explicitly, and in the actual generate_report it is called directly via rmarkdown::render().
So - I am at a complete loss.
Thoughts and suggestions would be completely appreciated.
So pandoc is apprently an executable that helps convert files from one extension to another. RStudio comes with its own pandoc executable so when running the scripts from RStudio, it knew where to point when pandoc is required.
From the command prompt, the system did not know to look inside of RStudio, so simply downloading pandoc as a standalone executable gives the system the proper pointer.
Downloded pandoc and everything works fine.

testthat error on check() but not on test() because of ~/.Rprofile?

EDIT:
Is it possible that ~/.Rprofile is not loaded on within check(). It looks like my whole process fails since the ~/.Rprofile is not loaded.
DONE EDIT
I have a strange problem on automated testing with testthat. Actually, when I test my package with test() everything works fine. But when I test with check() I get an error message.
The error message says:
1. Failure (at test_DML_create_folder_start_MQ_script.R#43): DML create folder start MQ Script works with "../DML_IC_MQ_DATA/dummy_data" data
capture.output(messages <- source(basename(script_file))) threw an error
Error in sprintf("%s folder got created for each raw file.", subfolder_prefix) :
object 'subfolder_prefix' not found
Before this error I source a script which defines the subfolder_prefix variable and I guess this is why it works in the test() case. But I expected to get this running in the check() function as well.
I will post the complete test script here, hope it is not to complicated:
library(testthat)
context("testing DML create folder and start MQ script")
test_dir <- 'dml_ic_mq_test'
start_dir <- getwd()
# list of test file folders
data_folders <- list.dirs('../DML_IC_MQ_DATA', recursive=FALSE)
for(folder in data_folders) { # for each folder with test files
dir.create(test_dir)
setwd(test_dir)
script_file <- a.DML_prepare_IC.script(dbg_level=Inf) # returns filename I will source
test_that(sprintf('we could copy all files from "%s".',
folder), {
expect_that(
all(file.copy(list.files(file.path('..',folder), full.names=TRUE),
'.',
recursive=TRUE)),
is_true())
})
test_that(sprintf('DML create folder start MQ Script works with "%s" data', folder), {
expect_that(capture.output(messages <- source(basename(script_file))),
not(throws_error()))
})
count_rawfiles <- length(list.files(pattern='.raw$'))
created_folders <- list.dirs(recursive=FALSE)
test_that(sprintf('%s folder got created for each raw file.',
subfolder_prefix), {
expect_equal(length(grep(subfolder_prefix, created_folders)),
count_rawfiles)
})
setwd(start_dir)
unlink(test_dir, recursive=TRUE)
}
In my script I define the variable subfolder_prefix <- 'IC_' and within the test I check if the same number of folders are created for each raw file... This is what my script should do...
So as I said, I am not sure how to debug this problem here since test() works but check() fails during the testthat run.
Now that I know to look in devtools we can find the answer. Per the docs check "automatically builds and checks a source package, using all known best practices". That includes ignoring .Rprofile. It looks like check calls build and that all of that work is done is a separate (clean) R session. In contrast test appears to use your currently running session (in a new environment).

.Last() in .RProfile doesn't execute

I'm trying to make R restart on quit, so I'm using .Last in my .Rprofile.
Solution modified from Quit and restart a clean R session from within R?, and I've tried the other solutions in that answer to no avail.
my .First() works fine, but when I q() at the end, it prompts for "save workspace image?" and after answering, it insta-closes
.Last <- function()
{
print("new R in 3 seconds")
Sys.sleep(3)
system("R --no-save")
print("close R in 3 seconds")
Sys.sleep(3)
}
print("test")
(the print at the end is because there's a hidden "feature" where .Rprofile ignores the last line if theres no newline, I know it shouldn't execute that.)

Difference between .Rprofile and .First

This might be straightforward, but I still feel frustrated, so I'd appreciate some quick explanation. I have extensively looked for a proper answer, but cannot seem to find one.
Since my .Rprofile includes all the commands that I need to run every time I open Rstudio (or R in general), why do I have the optionality to define the .First() function within the .Rprofile? What is it really the purpose of .First()?
To give an example, suppose that my .Rprofile has the following lines:
.First <- function(){
library(xts)
cat("\nWelcome at", date(), "\n")
}
How different is the above from simply having in my .Rprofile the lines:
library(xts)
cat("\nWelcome at", date(), "\n")
I have tried both and they do have the same outcome.
Thanks!
The main difference is that .First is executed after the default workspace image .Rdata (if it exists) is loaded, and so has access to objects in that workspace.
For example, let's create an object that will be automatically loaded on startup:
x <- 2
save.image()
Quit R, and create a .RProfile in your default working directory containing:
y <- try(print(x))
print(y)
.First <- function()
{
print(x)
invisible(NULL)
}
The first attempt to print x should fail, but the second should succeed.

Resources