Writing to file in R one line after the other - r

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")

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

How to simultaneously read and write a file line by line?

I would like to remove all lines from a file which start with a certain pattern. I would like to do this with R. It is good practice to not first read the whole file, then remove all matching lines and afterwards write the whole file, as the file can be huge. I am thus wondering if I can have both a read and a write connection (open all the time, one at a time?) to the same file. The following shows the idea (but 'hangs' and thus fails).
## Create an example file
fnm <- "foo.txt" # file name
sink(fnm)
cat("Hello\n## ----\nworld\n")
sink()
## Read the file 'fnm' one line at a time and write it back to 'fnm'
## if it does *not* contain the pattern 'pat'
pat <- "## ----" # pattern
while(TRUE) {
rcon <- file(fnm, "r") # read connection
line <- readLines(rcon, n = 1) # read one line
close(rcon)
if(length(line) == 0) { # end of file
break
} else {
if(!grepl(pat, line)) {
wcon <- file(fnm, "w")
writeLines(line, con = wcon)
close(wcon)
}
}
}
Note:
1) See here for an answer if one writes to a new file. One could then delete the old file and rename the new one to the old one, but that does not seem very elegant :-).
2) Update: The following MWE produces
Hello
world
-
world
See:
## Create an example file
fnm <- "foo.txt" # file name
sink(fnm)
cat("Hello\n## ----\nworld\n")
sink()
## Read the file 'fnm' one line at a time and write it back to 'fnm'
## if it does *not* contain the pattern 'pat'
pat <- "## ----" # pattern
con <- file(fnm, "r+") # read and write connection
while(TRUE) {
line <- readLines(con, n = 1L) # read one line
if(length(line) == 0) break # end of file
if(!grepl(pat, line))
writeLines(line, con = con)
}
close(con)
I think you just need open = 'r+'. From ?file:
Modes
"r+", "r+b" -- Open for reading and writing.
I don't have your sample file, so I'll instead just have the following minimal example:
take a file with a-z on 26 lines and replace them one by one with A-Z:
tmp = tempfile()
writeLines(letters, tmp)
f = file(tmp, 'r+')
while (TRUE) {
l = readLines(f, n = 1L)
if (!length(l)) break
writeLines(LETTERS[match(l, letters)], f)
}
close(f)
readLines(f) afterwards confirms this worked.
I understand you want to use R, but just in case you're not aware, there are some really simple scripting tools that excel in this type of task. E.g gawk is designed for pretty much exactly this type of operation and is simple enough to learn that you could write a script for this within minutes even without any prior knowledge.
Here's a one-liner to do this in gawk (or awk if you are on Unix):
gawk -i inplace '!/^pat/ {print}' foo.txt
Of course, it is trivial to do this from within R using
system(paste0("gawk -i inplace '!/^", pat, "/ {print}' ", fnm))

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

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.

When i wirte to file in R it always puts the values on a new line

when i write my vector to a file it always places it on a new line. How can I stop this. see my code below. Each variable in x is written to a new line.
x<- c(compname,mean(askspread),median(askspread),mean(q, na.rm=TRUE),median(q, na.rm=TRUE),max(q, na.rm=TRUE),timeticks,"\n")
write(x, file = "/testdata.txt",append=TRUE,sep = ",")
x <- paste(compname,mean(askspread),median(askspread),mean(q, na.rm=TRUE),median(q, na.rm=TRUE),max(q, na.rm=TRUE),timeticks,"\n", sep = ",")

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