How to use .first() function in R in .Rdata mode - r

I'm trying to customize my R setup. I understood the part where we can put our functions(.First/Last) in Rprofile.site or .Rprofile. but I want to take .Rdata route. As I understand that if I have a .First/.Last function in any of the .R file in my working directory. Then when I open my .Rdata file my custom setting should be loaded.
Though I get an Adios when I quit the session but I don't get anything when I open my .Rdata. Anyway, below are my .First and .Last function.
.First <- function() {
options(prompt="$ ", continue="+\t") # $ is the prompt
options(digits=5, length=999)
cat(paste(date(),"\nWelcome\n"))
# custom numbers and printout
x11() # for graphics
par(pch = "+")
# my personal functions
library(cluster) # attach a package
s <- base::summary
h <- utils::head
n <- base::names
}
.Last <- function() {
graphics.off() # a small safety measure.
cat(paste(date(),"\nAdios\n")) # Is it time for lunch?
}

Related

Clarity on issue with nested functions and environments in R

I created a function to save data to a specific location which is loaded as part of a package when launching rstudio:
save_data <- function(fileName, file_name){
file_path <- paste0("~/", file_name)
save(list=deparse(substitute(fileName)), file=file_path)
}
but when calling this function from inside another function it returns an "Error saving the following file: ...".
To reproduce the issue I created a savetestfunction:
savetest <- function(fileName){
data1 <- fileName * 10
save_data(data1, file_name = "test.RData")
data1
}
and a small savetestscript:
source("savetestfunction.R")
x <- c(1:10)
data1 <- savetest(x)
I spent a long time assuming the issue stemmed from the environments and what was being seen from each (e.g. save_data function loaded on startup couldn't see the temporary environment created when calling the savetestfunction) but as a test I tried adding a print(fileName) to the save_data function and to my surprise it could in fact see what fileName was at this point.
The Fix: I updated the function so that it assigned fileName within the environment created by the save_data function and it now functions as intended...
save_data <- function(fileName, file_name){
file_path <- paste0("//placeholder//", file_name)
assign(deparse(substitute(fileName)), fileName)
save(list=deparse(substitute(fileName)), file=file_path)
}
The Confusion: This then led me to believe that fileName was perhaps a promise when it was being saved however save() contains an argument eval.promises which is True by default so it can't be this!
The Question: What was causing this issue? (Confusion related to environments? Promises?) What could have been done to avoid this?
Edit: Tried to use saveRDS but didn't have success with this. More interested in why the save doesn't work in the first place rather than an actual fix as the assign within the save_data function already lets it function.

Suppress Messages from zip in R

I want to suppress the messages as outputted by the zip command in r but I fail to find the right command to do so.
Background, as I use the zip-function within a function, I don't want the user to see all information about all the files (roughly 5.000, which clutters the console).
Here is what I have tried so far, but all functions foo show either adding: hw.txt (stored 0%) or updating: hw.txt (stored 0%)
# create a small file
writeLines("hello world", "hw.txt")
# use the original command
zip("zip.zip", "hw.txt")
# try different options of capturing/suppressing output!
# assignment
foo1 <- function() a <- zip("zip.zip", "hw.txt")
foo1()
# capture.output
foo2 <- function() a <- capture.output(zip("zip.zip", "hw.txt"))
foo2()
# suppressMessages
foo3 <- function() suppressMessages(zip("zip.zip", "hw.txt"))
foo3()
# invisible
foo4 <- function() invisible(zip("zip.zip", "hw.txt"))
foo4()
# sink
foo5 <- function() {
sink(tempfile())
zip("zip.zip", "hw.txt")
sink()
}
foo5()
Are there any other options to suppress the output of zip?
The answer will depend on the system that the code is used on. On my Windows system, I can use
zip("zip.zip", "hw.txt", flags="-q")
and it suppresses messages, but it depends on what your system uses to handle zip files. Since the message is coming from the zip program, you must signal it not to output messages.

How to automatically load a function

I have created some functions in R and whenever I need any of those functions, I need to re-create that. Please suggest me the way and steps so that i can use directly those functions in any session of R without recreating them.
While Carl's answer is acceptable, I personally think that this is exactly the situation where you should package your functions and simply call them as a library.
There are very good reasons to do this:
Documentation (with emphasis!)
Tests
Easy loading (library(mypackage))
Easy to share and portable across systems
Easy to use within reporting (Rmd/knitr)
Reduces potential for duplication
Learning the R package system will be a strong part of your toolbox and other benefits of organizing your code appropriately will become apparent.
I have a series of functions that I need across all sessions. The trick is to add them to your .First file so that they are sourced into every session globally.
A helper function to find your first-file
find.first <- function(edit = FALSE, show_lib = TRUE){
candidates <- c(Sys.getenv("R_PROFILE"),
file.path(Sys.getenv("R_HOME"), "etc", "Rprofile.site"),
Sys.getenv("R_PROFILE_USER"),
file.path(getwd(), ".Rprofile")
)
first_hit <- Filter(file.exists, candidates)
if(show_lib & !edit){
return(first_hit)
}else {
file.edit(first_hit)
}
}
Say your scripts you use everywhere are in '/mystuff/R'
# Pop open the first Rprofile file.
find.first(edit = TRUE)
You will see something like this:
##Emacs please make this -*- R -*-
## empty Rprofile.site for R on Debian
##
## Copyright (C) 2008 Dirk Eddelbuettel and GPL'ed
##
## see help(Startup) for documentation on ~/.Rprofile and Rprofile.site
# ## Example of .Rprofile
# options(width=65, digits=5)
# options(show.signif.stars=FALSE)
# setHook(packageEvent("grDevices", "onLoad"),
# function(...) grDevices::ps.options(horizontal=FALSE))
# set.seed(1234)
#.First <- function(){}
#
#
Edit the function to something like:
.First <- function(){
all_my_r <- list.files('/mystuff/R', full.names = T,
recursive = T, pattern = ".R$" )
lapply(all_my_r, function(i){
tryCatch(source(i), error = function(e)NULL)
})
}
Save the file. Then restart the session.

Change knitr chunk defaults outside documents

I teach a lab and I have my students write their answers in .Rmd files. For grading, I download and render them as pdfs in a batch. I use the following script to render everything and save in a file.
library(rmarkdown)
# Handy functions for concatenating strings because I want to do it like a Python
# programmer damnit!
`%s%` <- function(x,y) {paste(x,y)}
`%s0%` <- function(x,y) {paste0(x,y)}
# You should set the working directory to the one where the assignments are
# located. Also, make sure ONLY .rmd files are there; anything else may cause
# a problem.
subs <- list.files(getwd()) # Get list of files in working directory
errorfiles <- c() # A vector for names of files that produced errors
for (f in subs) {
print(f)
tryCatch({
# Try to turn the document into a PDF file and save in a pdfs subdirectory
# (you don't need to make the subdirectory; it will be created automatically
# if it does not exist).
render(f, pdf_document(), output_dir = getwd() %s0% "/pdfs")
},
# If an error happens, complain, then save the name in errorfiles
error = function(c) {
warning("File" %s% "did not render!")
warning(c)
errorfiles <- c(errorfiles, f)
})
}
This last assignment I forgot to set error=TRUE in the chunks, so documents will fail to compile if errors are found and I will have to go hunt those errors down and fix them. I tried to modify this code so that I set the parameter error=TRUE as default outside the document. Unfortunately, I've been working at this for hours and have found no way to do so.
How can I change this code so I can change this parameter outside the documents? (Bear in mind that I don't own the computer so I cannot install anything, but the packages knitr and rmarkdown are installed.)

R sometimes does not save my history

I have a program in R. Sometimes when I save history, they do not write into my history file. I lost some histories a few times and this really drive me crazy.
Any recommendation on how to avoid this?
First check your working directory (getwd()). savehistory() saves the history in the current working directory. And to be honest, you better specify the filename, as the default is .History. Say :
savehistory('C:/MyWorkingDir/MySession.RHistory')
which allows you to :
loadhistory('C:/MyWorkingDir/MySession.RHistory')
So the history is not lost, it's just in a place and under a name you weren't aware of. See also ?history.
To clarify : the history is no more than a text file containing all commands of that current session. So it's a nice log of what you've done, but I almost never use it. I construct my "analysis log" myself by using scripts, as hinted in another answer.
#Stedy has provided a workable solution to your immediate question. I would encourage you to learn how to use .R files and a proper text editor, or use an integrated development environment (see this SO page for suggestions). You can then source() in your .R file so that you can consistently replicate your analysis.
For even better replicability, invest the time into learning Sweave. You'll be glad you did.
Check the Rstudio_Desktop/history_database file - it stores every command for any working directory.
See here for more details How to save the whole sequence of commands from a specific day to a file?
Logging your console on a regular basis to **dated* files is handy. The package TeachingDemos has a great function for logging your console session, but it's written as a singleton, which is problematic for automatic logging, since you wouldn't be able to use that function to create teaching demo's if you use it for logging. I re-used that function using a bit of meta-programming to make a copy of that functionality that I include in the .First function in my local .Rprofile, as follows:
.Logger <- (function(){
# copy local versions of the txtStart,
locStart <- TeachingDemos::txtStart
locStop <- TeachingDemos::txtStop
locR2txt <- TeachingDemos:::R2txt
# creat a local environment and link it to each function
.e. <- new.env()
.e.$R2txt.vars <- new.env()
environment(locStart) <- .e.
environment(locStop) <- .e.
environment(locR2txt) <- .e.
# reference the local functions in the calls to `addTaskCallback`
# and `removeTaskCallback`
body(locStart)[[length(body(locStart))-1]] <-
substitute(addTaskCallback(locR2txt, name='locR2txt'))
body(locStop)[[2]] <-
substitute(removeTaskCallback('locR2txt'))
list(start=function(logDir){
op <- options()
locStart(file.path(logDir,format(Sys.time(), "%Y_%m_%d_%H_%M_%S.txt")),
results=FALSE)
options(op)
}, stop = function(){
op <- options()
locStop()
options(op)
})
})()
.First <- function(){
if( interactive() ){
# JUST FOR FUN
cat("\nWelcome",Sys.info()['login'],"at", date(), "\n")
if('fortunes' %in% utils::installed.packages()[,1] )
print(fortunes::fortune())
# CONSTANTS
TIME <- Sys.time()
logDir <- "~/temp/Rconsole.logfiles"
# CREATE THE TEMP DIRECORY IF IT DOES NOT ALREADY EXIST
dir.create(logDir, showWarnings = FALSE)
# DELETE FILES OLDER THAN A WEEK
for(fname in list.files(logDir))
if(difftime(TIME,
file.info(file.path(logDir,fname))$mtime,
units="days") > 7 )
file.remove(file.path(logDir,fname))
# sink() A COPY OF THE TERMINAL OUTPUT TO A DATED LOG FILE
if('TeachingDemos' %in% utils::installed.packages()[,1] )
.Logger$start(logDir)
else
cat('install package `TeachingDemos` to enable console logging')
}
}
.Last <- function(){
.Logger$stop()
}
This causes a copy of the terminal contents to be copied to a dated log file. The nice thing about having dated files is that if you use multiple R sessions the log files won't conflict, unless you start multiple interactive sessions in the same second).

Resources