I am writing a program to generate whisker template in a loop, and I want to paste them together. For every template, my code looks like this:
script[i] <- whisker.render(template_pdf[i], data = parameter)
Is there a method to paste all the script[i] together? I know I can paste all the chunks first and then use function whisker.render just for one time, but that will cause some trouble in my particular case. If I can paste all the script[i] together, that will be convenient for me.
When script is a character vector you can do
paste(script, collapse = "\n")
with \n (newline) the character inserted between the script elements.
When script is a list, you can do
do.call(paste, c(script, sep ="\n"))
Related
I am using some simple bash commands inside of an R for-loop to create some files with unique names.
Since the command arguments change with each iteration, I thought of using eval(parse(text=paste(system2(...)))), something like this:
index <- 1:5
for (i in index){
eval(parse(text=paste('system2("echo","`some text`>> myfile_',i,'.txt")',sep = "")))
}
However, to define the text string that is the argument to echo, I need a third delimiter because single, double and back quotes don't work. The above code with back quotes produces five lines of:
sh: some: command not found
while using the other quotes produces other errors.
Are there other delimiters that will work in this case?
is it possible to indent output in R?
e.g.
cat("text1\n")
indent.switch(indent=4)
cat("random text\n")
print("another random text")
indent.switch(indent=0)
cat("text2\n")
resulting in
text1
random text
another random text
text2
I searched for this a few months ago, found nothing and am now searching again.
My current idea is to "overwrite" (I forgot the special term) the functions cat and/or print with an additional argument like:
cat("random text", indent=4)
Only I'm stuck with this and I dont like this procedure very much.
Any ideas?
Edit:
I should be more particular, nevertheless thank you for the \t (omg, i totally forgot this -.-) and that I can format it inside cat.
The given solutions work, but only solve my second-choice-path.
A switch as shown in my first codeexample does not exist I suppose?
My problem is that I have parts of a bigger program which have multiple subscripts, and the output of each subscript should be indented. This is absolutely possible with the "\t" or just blanks inside cat() but has to be done in every command, which I dont like very much.
Solution
I used Chris C's code and extended it in a very easy way. (Thank you very much Chris!)
define.catt <- function(ntab = NULL, nspace=NULL){
catt <- function(input = NULL){
if(!is.null(ntab)) cat(paste0(paste(rep("\t", ntab), collapse = ""), input))
if(!is.null(nspace)) cat(paste0(paste(rep(" ", nspace), collapse = ""), input))
if(is.null(ntab) && is.null(nspace)) cat(input)
}
return(catt)
}
The same way you used \n to print a newline, you can use \t to print a tab.
E.g.
cat("Parent level \n \t Child level \n \t \t Double Child \n \t Child \n Parent level")
Evaluates to
Parent level
Child level
Double Child
Child
Parent level
As an alternative, you can create a derivative of cat called catt and alter options depending on the script. For example.
define.catt <- function(ntab = NULL){
catt <- function(input = NULL){
cat(paste0(paste(rep("\t", ntab), collapse = ""), input))
}
return(catt)
}
You would then set catt with however many tabs you wanted by
catt <- define.catt(ntab = 1)
catt("hi")
hi
catt <- define.catt(ntab = 2)
catt("hi")
hi
And just use catt() instead of cat().
You may consider the very versatile function capture.output(...), which evaluates the '...' list of expressions provided as main input arguments, and stores the text output (as if it would be displayed in the console) into a character vector instead. Then, you simply have to modify the strings as desired: here you want to add some leading spaces to each string. Finally, you write the strings to the console.
These can be done all in one line of nested calls. For example:
writeLines(paste(" ", capture.output(print(head(iris))), sep=""))
I therefore recommend you all to read the help of the capture.output function, and then try to use it for various purposes. Indeed, since the main input has the usual flexibility of the '...' list-like structure, you are free to include, for instance, a call to one home-made function, and thus do almost anything. As for indentation, that is simply done with paste function, once the former has done its magic.
I'm using base::paste in a for loop:
for (k in 1:length(summary$pro))
{
if (k == 1)
mp <- summary$pro[k]
else
mp <- paste(mp, summary$pro[k], sep = ",")
}
mp comes out as one big string, where the elements are separated by commas.
For example mp is "1,2,3,4,5,6"
Then, I want to put mp in a file, where each of its elements is added to a separate column in the same row. My code for this is:
write.table(mp, file = recompdatafile, sep = ",")
However, mp just appears in the CSV as one big string as opposed to being divided up. How can I achieve my desired format?
FYI
I've also tried converting mp to a list, and strsplit()-ing it, neither of which have worked.
Once I've added summary$pro to the file, how can I also add summary$me (which has the same format), in one row with multiple columns?
Thanks,
n.i.
If you want to write something to a file, write.table() isn't the only way. If you want to avoid headers and quotes and such, you can use the more direct cat. For example
cat(summary$pro, sep=",", file="filename.txt")
will write out the vector of values from summary$pro separated by commas more directly. You don't need to build a string first. (And building a string one element at a time as you did above is a bad practice anyway. Most functions in R can operate on an entire vector at a time, including paste).
I am trying to create a function that will calculate the frequency count of keywords using TM package. The function works fine if the text pasted from readline is on free form text without a new line. The problem is, when I paste a bunch of text copied from a spreadsheet, readline considers it as a new line.
keyword <- function() {
x <- readline(as.character('Input text here: '))
x <- Corpus(VectorSource(x))
...
tdm <- TermDocumentMatrix(x)
...
tdm
}
Here's the full code: https://github.com/CSCDataAnalytics/PM-Analysis/blob/master/Keyword.R
How can I prevent this from happening or at least consider a bunch of text of every row from the spreadsheet as one vector only?
If I'm understanding you correctly, the problem is when the user pastes the text from another application: the newline is causing R to stop accepting the subsequent lines.
One technique (fragile as it may be) is to look for a specific line, such as an empty line "" or a period ".". It's a little fragile because now you need (1) assurance that the data will "never" include that as a whole line, and (2) it is easily appended by the user.
Try:
endofinput <- ""
totalstr <- ""
while(! endofinput == (x <- readline('prompt (empty string when done): ')))
totalstr <- paste(totalstr, x)
In this case, the empty string is the catch, and when the while loop is done, totalstr contains all input separated by a space (this can be changed in the paste function).
NB: one problem with this technique is that it is "growing" the vector totalstr, which will eventually cause performance penalties (depending on the size of the input data): every loop iteration, more memory is allocated and the entire string is copied plus the new line of text. There are more verbose ways to side-step this problem (e.g., pre-allocate a vector larger than your anticipated input data), but if you aren't anticipated 1000s of lines then you may be able to accept this naive programming for simplicity.
Another option would be to have the user save the data to a text file and use file.choose() and readLines() to get your data.
Try collapsing the data into a single string after using readline
x <- paste(readline(as.character('Input text here: ')), collapse=' ')
Couldn't see a solution online but I thought this might be quite common.
with write.csv I basically always have the argument row.name set to F. Is it possible to run a line once and update the default value of the argument for the rest of the session?
I tried paste <- paste(sep="") which ran and returned no error but seemed to do nothing (and didn't destroy the paste function). This is another one, I always set sep="" with paste...
like I always have exclude=NULL when I am using table so I can see the N/A values.
EDIT: So, I'm looking for a solution that will work for multiple functions if possible: paste, write.csv, table and other functions like these.
paste <- paste(sep="") puts the output of paste() into an object named "paste". You would need to do something like this instead.
paste <- function (..., sep = "", collapse = NULL) {
base::paste(..., sep=sep, collapse=collapse)
}
You can also look at the Defaults package for this sort of thing, but it doesn't currently work for two of your examples.
Try this:
paste <- paste
formals(paste)$sep <- ""
This creates a new copy of paste in your workspace, and then modifies its default value for sep to "". Subsequent calls to paste will then use the modified copy, as it sits in front of the base environment in your search path.