Set two paths to point to the same path - r

I am sharing most of my codes with my colleague and in doing so we have different root directories we need to edit to run the code. For example, I am accessing all my files in:
/usethis/mypath/mydir/now_same/mapk/
and he is in:
/media/hispath/hisdir/now_same/mapk/
what I want to do is for any subsequent path directions to access any files/subroutines in the code,
I want to point to my directory, i.e.(/usethis/mypath/mydir/) and without changing anything afterwards, i.e. (/now_same/mapk/). So if he sends me code with /media/hispath/hisdir/now_same/mapk/, I just want to use it without changing anything in the code.
How do we do it?

Pass working director as argument, see example:
myScript.R
args <- commandArgs(trailingOnly = TRUE)
setwd(args[1])
# other code
# ...
# end of myScript.R
Now to run the script with custom working directory:
Rscript myScript.R path/to/my/directory

Related

Finding if my function inside an rscript file is been called by either an rmarkdown or an rscript

I have a function in an Rscript (this is inside an r-package of my own) that is been called either by an .R(Rscript) file or an .Rmd(rmarkdown).
I need to create an if statement inside this function to do things depending if the function is called by either the Rscript or the Rmarkdown.
In my case the following solves the issue
Getting the file path that also includes filename and extension:
file_type <- try(rstudioapi::getSourceEditorContext()$path, silent = T)
Getting the file extension.
file_type <- tools::file_ext(file_type)
Then iff file_type = 'R' the functionalities are turned on and for any other cases they are off.
if(file_type == 'R'){
...
}
In this specific case I only care that the extension is a '.R' and don't want to risk using the functionalities with anything else.
For example if you are running the function in the console then file_type = '' and the functionalities will be off.

Saving history for script run Rscript through terminal/console

for my work, I run scripts on virtual machines on a computer cluster. These jobs are typically large and have a big output. What I'd like to do is to run a script via the terminal. In the end, the script creates a duplicate of itself so that it contains every line that was part of the script (minus the last if necessary). This is quite vital for replicability and debugging in my work-life because I sometimes can't see which parameters or variables a particular job included as I submit the same script repeatedly just with slightly different parameters and the folders can't be version controlled.
Imagine this file test.R:
a <- rnorm(100)
#test
# Saving history for reproducibility to folder
savehistory(file = 'test2.R')
Now, I run this via the console on my virtual node and get the following error:
[XX home]$ Rscript test.R
Error in.External2(C_savehistory, file): no history available to save
Calls: save history
Execution halted
Is there any command like save history that works inside a script that is just executed?
The desired outcome is a file called test2.R is saved that contains this:
a <- rnorm(100)
#test
# Saving history for reproducibility to folder
You could copy the file instead. Since you're using Rscript, the script name is included in commandArgs() in the form --file=test.R. A simple function like this will return the path of the executing script:
get_filename <- function() {
c_args <- commandArgs()
r_file <- c_args[grepl("\\.R$", c_args, ignore.case = TRUE)]
r_file <- gsub("--file=", "", r_file)
r_file <- normalizePath(r_file)
return(r_file)
}
Then you can copy the file as you see fit. For example, appending ".backup":
script_name <- get_filename()
backup_name <- paste0(script_name, ".backup")
file.copy(script_name, backup_name)

User input and output path of files in R

I am aiming to write an R script that would take the user path for the file and output name of the file. This will be followed by its processing and then output being stored in that file.
Normally, if I had to break this code on R studio it will look like this:
d<- read.table("data.txt" , header =T)
r<-summary(d)
print(r)
the output that is being displayed is also to be written in output file.
where data.txt is
1
2
3
4
45
58
10
What I would like to do is to put the code in a file called script.R and then run it as follows
R script.R input_file_path_name output_file_name
Could anyone spare a minute or two and help me out.
Many thanks in advance.
The most natural way to pass arguments from the command line is to use the function commandArgs. This function scans the arguments which have been supplied when the current R session was invoked. So creating a script named sillyScript.R which starts with
#!/usr/bin/env Rscript
args = commandArgs(trailingOnly=TRUE)
and running the following command line
Rscript --vanilla sillyScript.R iris.txt out.txt
will create a string vector args which contains the entries iris.txt and out.txt.
Use the args[1] and args[2] vector as the input and outputfile paths.
https://www.r-bloggers.com/passing-arguments-to-an-r-script-from-command-lines/
You can consider this method:
script<-function(input_file){
input_file<-read.table("data.txt", header=T)
r<- summary(input_file)
return(r)}
If you want to manually choose the input file location you can use:
read.table(file.choose(),header=T)
Just executing the script with the input name is sufficient to return the desired output. For eg,
output_file<-script(input_file)
If you also want to export the data from R, you can modify the script as follows:
script<-function(input_file,output_file_name){
input_file<-read.table("data.txt", header=T)
r<- summary(input_file)
write.table(r,paste0(output_file_name,".txt",collapse="")
return(r)}
You have to use file name within inverted commas:
> vector<- script(input_file,"output_file_name")
By default, the output will be exported to current R directory. You can also specify output file location by putting the file location before output file_name within the script:
write.table(r,paste0("output_location",output_file_name,".txt",collapse="")

How to pass several files to a command function and output them to different files?

I have a directory made of 50 files, here's an excerpt about how the files are names :
input1.txt
input2.txt
input3.txt
input4.txt
I'm writing the script in R but I'm using bash commands inside it using "system"
I have a system command X that takes one file and outputs it to one file
example :
X input1.txt output1.txt
I want input1.txt to output to output1.txt, input2.txt to output to output2.txt etc..
I've been trying this:
for(i in 1:50)
{
setwd("outputdir");
create.file(paste("output",i,".txt",sep=""));
setwd("homedir");
system(paste("/usr/local/bin/command" , paste("input",i,".txt",sep=""),paste("/outputdir/output",i,".txt",sep="")));
}
What am I doing wrong? I'm getting an error at the line of system , it says incorrect string constant , I don't get it.. Did I apply the system command in a wrong manner?
Is there a way to get all the input files and output files without going through the paste command to get them inside system?
There is a pretty easy method in R to copy files to a new directory without using the system commands. This also has the benefit of being cross-capable on different operating systems (just have to change the files structures).
Modified code from: "Copying files with R" by Amy Whitehead
Using your method of running for files 1:50 I have some psudocode here. You will need to change the current.folder and new.folder to something
# identify the folders
current.folder <- "/usr/local/bin/command"
new.folder <- "/outputdir/output"
# find the files that you want
i <- 1:50
# Instead of looping we can use vector pasting to get multiple results at once!
inputfiles <- paste0(current.folder,"/input",i,".txt")
outputfiles <- paste0(new.folder,"/output",i,".txt")
# copy the files to the new folder
file.copy(inputfiles, outputfiles)

Copy script after executing

Is there a possibility to copy the executed lines or basically the script into the working directory?
So my normal scenario is, I have stand alone script which just need to be sourced within a working directory and they will do everything I need.
After a few month, I made update to these scripts and I would love to have a snapshot from the script when I executed the source...
So basically file.copy(ITSELF, '.') or something like this.
I think this is what you're looking for:
file.copy(sys.frame(1)$ofile,
to = file.path(dirname(sys.frame(1)$ofile),
paste0(Sys.Date(), ".R")))
This will take the current file and copy it to a new file in the same directory with the name of currentDate.R, so for example 2015-07-14.R
If you want to copy to the working directory instead of the original script directory, use
file.copy(sys.frame(1)$ofile,
to = file.path(getwd(),
paste0(Sys.Date(), ".R")))
Just note that the sys.frame(1)$ofile only works if a saved script is sourced, trying to run it in terminal will fail. It is worth mentioning though that this might not be the best practice. Perhaps looking into a version control system would be better.
Explanation:
TBH, I might not be the best person to explain this (I copied this idea from somewhere and use it sometimes), but I'll try. Basically in order to have information about the script file R needs to be running it as a file inside an environment with that information, and when that environment is a source call it contains the ofile data. We use (1) to select the next (source()'s) environment following the global environment (which is 0). When you're running this from terminal, there's no frame/environment other than Global (that's the error message), since no file is being ran - the commands are sent straight to terminal.
To illustrate that, we can do a simple test:
> sys.frame(1)
Error in sys.frame(1) : not that many frames on the stack
But if we call that from another function:
> myf <- function() sys.frame(1)
> myf()
<environment: 0x0000000013ad7638>
Our function's environment doesn't have anything in it, so it exists but, in this case, does not have ofile:
> myf <- function() names(sys.frame(1))
> myf()
character(0)
I just wanted to add my solution since I decided to use a try function before executing the copy command... Because I have the feeling I miss some control...
try({
script_name <- sys.frame(1)$ofile
copy_script_name <-
paste0(sub('\\.R', '', basename(script_name)),
'_',
format(Sys.time(), '%Y%m%d%H%M%S'),
'.R')
file.copy(script_name,
copy_script_name)
})
This will copy the script into the current directory and also adds a timestamp to the filename. In case something goes wrong, the rest of the script will still execute.
I originally posted this other thread, and I think it addresses your problem: https://stackoverflow.com/a/62781925/9076267
In my case, I needed a way to copy the executing file to back up the original >script together with its outputs. This is relatively important in research.
What worked for me while running my script on the command line, was a mixure of >other solutions presented here, that looks like this:
library(scriptName)
file_dir <- paste0(gsub("\\", "/", fileSnapshot()$path, fixed=TRUE))
file.copy(from = file.path(file_dir, scriptName::current_filename()) ,
to = file.path(getwd(), scriptName::current_filename()))
Alternatively, one can add to the file name the date and our to help in >distinguishing that file from the source like this:
file.copy(from = file.path(current_dir, current_filename()) ,
to = file.path(getwd(), subDir, paste0(current_filename(),"_", Sys.time(), ".R")))

Resources