Is there a way to make R strings verbatim (not escaped)? - r

Typical example:
path <- "C:/test/path" # great
path <- "C:\\test\\path" # also great
path <- "C:\test\path"
Error: '\p' is an unrecognized escape in character string starting ""C:\test\p"
(of course - \t is actually an escape character.)
Is there any mark that can be used to treat the string as verbatim? Or can it be coded?
It would be really useful when copy/pasting path names in Windows...

R 4.0.0 introduces raw strings:
dir <- r"(c:\Program files\R)"
https://stat.ethz.ch/R-manual/R-devel/library/base/html/Quotes.html
https://blog.revolutionanalytics.com/2020/04/r-400-is-released.html

You can use scan ( but only in interactive session -- not in source)
Like
path=scan(what="",allowEscapes=F,nlines=1)
C:\test\path
print(path)
And then
Ctrl+A ++ Ctrl+Enter
give you result
But not work in function or source :
{
path=scan(what="character",allowEscapes=F,nlines=1)
C:\test\path
print(path)
}
throw error

Maybe readline() or scan(what = "charactor"), both work in terminal, not script or function:
1.readline():
> path <- readline()
C:\test\path #paste your path, ENTER
> path
[1] "C:\\test\\path"
2.scan(what = "charactor"):
> path = scan(what = "character")
1: C:\test\path #paste, ENTER
2: #ENTER
#Read 1 item
> path
[1] "C:\\test\\path"
EDIT:
Try this:
1.Define a function getWindowsPath():
> getWindowsPath <- function() #define function
{
return(scan(file = "clipboard", what = "character"))
}
2.Copy windows path using CTRL+C:
#CTRL+C: C:\test\path
> getWindowsPath()
#Read 1 item
[1] "C:\\test\\path"

If you are copying and pasting in windows, you can set up a file connection to the clipboard. Then you can use scan to read from it, with allowEscapes turned off. However, Windows allows spaces in file paths, and scan doesn't understand that, so you have to wrap the result in paste0 with collapse set to a 0-length character string.
x = file(description = "clipboard")
y = paste0(scan(file = x, what = "character", allowEscapes = F), collapse = "")
Unfortunately, this only works for the path currently in the clipboard, so if you are copying and pasting lots of paths into an R script, this is not a solution. A workaround in that situation would be to paste each path into a separate text file and save it. Then, in your main script, you could run the following
y = paste0(scan(file = "path1.txt", what = "character", allowEscapes = F), collapse = "")
You would probably need one saved file for each path.

Related

R script output values into another folder or directory

After running my R script in the terminal I get two output data files: a.dat and b.dat. My goal is to directly divert these output files into a new folder.
Is there any way to do something like this:
Rscript myscript.R > folder
Note: For writing the output file I simply use this:
write(t(result1), file = "a.dat", ncolumns = 5, append=TRUE)
I solved my problem by doing the following:
I created an output folder 'output'
I added the full path of the output in myscript.R as
write(t(result1), file = "home/Documents/output/a.dat", ncolumns = 5, append=TRUE)
Solved! :)
You could simply use write.table create two csv files like this:
A minimal working example:
using a r-script called "Rfile.r" in the directory "adir" in my "Dokumente" folder. the script reads the first two inputs , a numeric as the input argument for the function , aswell as a character string with the output-target-directory . (you could also do filenames , etc of course..)
Rfile.r ::
# set arguments, to later specifiy in terminal ,
# one numeric and one target directory
arg <- commandArgs(trailingOnly = TRUE)
n<-as.numeric(arg[1])
path<-as.character(arg[2])
## A random function two create two csv 's
fun <- function(n) {
data.a <-data.frame(rep("Some Data", n))
data.b<-data.frame(rnorm(1:n))
data<-list(data.a,data.b)
return(data)
}
# create data using input arg[1], aka 'n'
data<-fun(n)
# now the important Part: using write.table with the arg[2] aka 'path'
# :
write.table(data[1],file =paste(path,"/data_a.csv", sep = ""))
write.table(data[2],file =paste(path,"/data_b.csv", sep = ""))
## write terminal output message using cat()
cat(paste("Your input was :" ,arg[1],sep="\t"),
paste( "your target path was:" ,arg[2] ,sep="\t"), sep = "\n")
then run in a terminal :
$ Rscript ~/Dokumente/adir/Rfile.r 3 ~/Dokumente/bdir
it creates two csv's in the directory "bdir" called "data_a.csv" and "data_b.csv" where 3 was the numeric input for the function in Rfile.r

Writing to file in R one line after the other

I have the following piece of code to write to an R file one line at a time.
for (i in c(1:10)){
writeLines(as.character(i),file("output.csv"))
}
It just writes 10 presumably over-writing the previous lines. How do I make R append the new line to the existing output? append = TRUE does not work.
append = TRUE does work when using the function cat (instead of writeLines), but only if you give cat a file name, not when you give it a file object: whether a file is being appended to or overwritten is a property of the file object itself, i.e. it needs to be specifried when the file is being opened.
Thus both of these work:
f = file('filename', open = 'a') # open in “a”ppend mode
for (i in 1 : 10) writeLines(i, f)
for (i in 1 : 10) cat(i, '\n', file = 'filename', sep = '', append = TRUE)
Calling file manually is almost never necessary in R.
… but as the other answer shows, you can (and should!) avoid the loop anyway.
You won't need a loop. Use newline escape charater \n as separator instead.
vec <- c(1:10)
writeLines(as.character(vec), file("output.csv"), sep="\n")

How to get the directory of the executing script in R? [duplicate]

This question already has answers here:
Determine path of the executing script
(30 answers)
Closed 4 years ago.
I have a function that looks like this:
read_data <- function(filename, header) {
path <- paste("./output/", filename, sep = "")
if (file.exists(path)) {
data <- read.csv(file = path, header = header, sep = ",")
}
# Partially removed for brevity.
}
What I want to achieve is that, given a filename, I want to search whether that filename is available inside the output subdirectory, which is a subdirectory where my script is located, and if it is available, I want to read that file. The problem is that as long as I know read.csv function's file argument requires a full path for the file. So, I somehow need to get the directory where my script is located, so I can concatenate it with the rest of the subdirectory and filename. I can get the current working directory with getwd(), but that's not quite the same thing, as my working directory seems always to be fixed, whereas the script can be located anywhere in the computer. Any ideas how to get the directory of the script, and concatenate it with the output subdirectory and the provided filename in R?
if you want to detemine the directory of the executing script, this might be a dup: Rscript: Determine path of the executing script
initial.options <- commandArgs(trailingOnly = FALSE)
file.arg.name <- "--file="
script.name <- sub(file.arg.name, "", initial.options[grep(file.arg.name, initial.options)])
script.dirname <- dirname(script.name)
print(script.dirname)
> f <- "/path/to/my/script.R"
> f
[1] "/path/to/my/script.R"
> basename(f)
[1] "script.R"
> dirname(f)
[1] "/path/to/my"
> dirname(dirname(f))
[1] "/path/to"
> file.path(dirname(f), "output")
[1] "/path/to/my/output"
> file.path(dirname(f), "output", "data.csv")
[1] "/path/to/my/output/data.csv"
Adding this as an answer for you Tinker.
Considering you're just trying to read in a file you can do it this way:
## So what does this do?
# The path is where the files exist
# The pattern is some identifiable portion of the file name, which list.files() will bring back
# You need the full name so that R knows where to read from, this way you don't have to set a new working directory.
data <- if(file.exists(list.files(path = "./output/", pattern = "filename",full.names=T))){ read.csv(list.files(path = "./output/", pattern = "filename",full.names=T))}
# Let's imagine you have a number of files to read in
# Generate a list of filenames
filename <- list("file1","file2","file3","filen")
data <- lapply( filename, function(x) {
if( file.exists( list.files( path = "./output/", pattern = x ,full.names=T ) ) ) {
read.csv( list.files(path = "./output/", pattern = x ,full.names=T) ) }
} )
# each element of the list is oe of your data files
data[[1]]
data[[2]]
data[[n]]
I'm not sure what you're declaring with header as csv's are assumed to have a header inherently, additionally a csv is comma separated so declaring the sep character is also redundant.
Collecting resources from multiple questions in SO, I came up with the following solution, that seems to work with multiple calling conventions:
library(base)
library(rstudioapi)
get_directory <- function() {
args <- commandArgs(trailingOnly = FALSE)
file <- "--file="
rstudio <- "RStudio"
match <- grep(rstudio, args)
if (length(match) > 0) {
return(dirname(rstudioapi::getSourceEditorContext()$path))
} else {
match <- grep(file, args)
if (length(match) > 0) {
return(dirname(normalizePath(sub(file, "", args[match]))))
} else {
return(dirname(normalizePath(sys.frames()[[1]]$ofile)))
}
}
}
Which later I can use as:
path <- paste(get_directory(), "/output/", filename, sep = "")

R scp and unzip - invalid zip name argument

I wonder if anyone can help me - I am trying to download a file using scp and then unzip it (it is a set of 100 files, so they have to be zipped and as well it excludes unz)
Basically first I run
x <- scp(host = "WM.net", path = "/wmdata.zip", user = "w", password = "wm")
it returns a raw object (of course it is a dummy address, you would not get anything, I cannot provide working site you can scp anything)
> class(x)
[1] "raw"
then I try to unzip it
b<-unzip(x)
Error in unzip(x) : invalid zip name argument
I tried to decompress it in memory but with no luck - the output is still raw, not a file list
z<-memDecompress(x, type = "unknown")
> class(z)
[1] "raw"
Where is my error? What am doing wrong? I have a vague feeling I need to save x to disc as zip, and then use unzip, but no idea how to save raw compressed value.
EDIT: I tried as well saving as a binary file via
f<-file("file.bin",open="wb") #or f<-file("file.zip",open="wb")
writeBin(x, f)
b <- unzip(f) #or b <- unzip("file.bin") or b <- unzip("file.zip")
and it produced a file after the first line, but after the second line the file is still empty and the unzip procedure returns the same zip name error
> class(f)
[1] "file" "connection"
> f
A connection with
description "file.zip"
class "file"
mode "wb"
text "binary"
opened "opened"
can read "no"
can write "yes"
The error you are getting is not unexpected at all, because unzip expects a file as its first parameter, and you are trying to pass a raw R vector, which is a vector of bytes. You can try first writing that raw vector to file, and then reading it using unzip. Something like this:
x <- scp(host = "WM.net", path = "/wmdata.zip", user = "w", password = "wm")
f <- file("path/to/your/file.bin", "wb")
writeBin(x, f)
b <- unzip(f)
This is not tested, but I wanted to point out the issues with how you were using the various APIs.

How to silently remove files in R

Given the following code:
x <- 1
save(x, file = "x")
file.remove("x")
The file.remove() command successfully removes the x file. However, it returns TRUE to the R console. How do I keep it from doing that?
I've tried things like file.remove("x", silent = TRUE), but it seems that whatever I add to the function is interpreted as a file name, since the above returns cannot remove file 'TRUE', reason 'No such file or directory'.
Try wrapping the call with invisible
x <- 1
save(x, file = "x")
invisible(file.remove("x"))

Resources