[R] writing R shell scripts?
Henrik Bengtsson
hb at maths.lth.se
Wed Nov 9 06:45:28 CET 2005
Mike Miller wrote:
>On Wed, 9 Nov 2005, Henrik Bengtsson wrote:
>
>
>
>>What you really want to do might be solved by write.table(), e.g.
>>
>>x <- matrix(rnorm(25*2),c(25,2));
>>write.table(file=stdout(), x, row.names=FALSE, col.names=FALSE);
>>
>>
>
>Thanks. That does what I want.
>
>There is one remaining problem for my "echo" method. While write.table
>seems to do the right thing for me, R seems to add an extra newline to the
>output when it closes. You can see that this produces exactly one newline
>and nothing else:
>
># echo '' | R --slave --no-save | wc -c
> 1
>
>Is there any way to stop R from sending an extra newline? It's funny
>because normal running of R doesn't seem to terminate by sending a newline
>to stdout. Oops -- I just figured it out. If I send "quit()", there is
>no extra newline! Examples that send no extra newline:
>
>echo 'quit()' | R --slave --no-save
>
>echo "x <- matrix(rnorm(25*2),c(25,2)); write.table(file=stdout(), x, row.names=FALSE, col.names=FALSE); quit()" | R --slave --no-save
>
>I suppose we can live with that as it is. Is this an intentional feature?
>
>
>
>
>>A note of concern: When writing batch scripts like this, be explicit and
>>use the print() statement. A counter example to compare
>>
>>echo "1; 2" | R --slave --no-save
>>
>>and
>>
>>echo "print(1); print(2)" | R --slave --no-save
>>
>>
>
>I guess you are saying that sometimes R will fail if I don't use print().
>Can you give an example of how it can fail?
>
>
What I was really try to say is that if you running the R terminal, that
is, you "sending" commands via the R prompt, R will take the *last*
value and call print() on it. This is why you get the result when you type
> 1+1
[1] 2
Without this "feature" you would have had to type
> print(1+1)
[1] 2
to get any results. Note that it is only the last value calculate, that
will be output this way, cf.
> 1+1; 2+2
[1] 4
In other words, in the latter example '1+1' is pretty useless and does
nothing but taking up CPU time. So, whenever you write batch scripts
like yours or standard R scripts called by source(), do use print()
explicitly (or cat() or write.table() or ...) if want output!
>>>By the way, I find it useful to have a script in my path that does
>>>this:
>>>
>>>#!/bin/sh
>>>echo "$1" | /usr/local/bin/R --slave --no-save
>>>
>>>Suppose that script was called "doR", then one could do things like
>>>this from the Linux/UNIX command line:
>>>
>>># doR 'sqrt(35.6)'
>>>[1] 5.966574
>>>
>>># doR 'runif(1)'
>>>[1] 0.8881654
>>>
>>>Which I find to be handy for quick arithmetic and even for much more
>>>sophisticated things. I'd like to get rid of the "[1]" though!
>>>
>>>
>>If you want to be lazy and not use, say, doR 'cat(runif(1),"\n")' above,
>>maybe a simple Unix sed in your shell script can fix that?!
>>
>>
>
>
>It looks like I can rewrite the script like this:
>
>#!/bin/sh
>echo "$1 ; write.table(file=stdout(), out, row.names=FALSE, col.names=FALSE); quit()" | /usr/local/bin/R --slave --no-save
>
>Then I have to always include something like this...
>
>out <- some_operation
>
>...as part of my command. Example:
>
>
>
Or go get the last value calculated by .Last.value, see
echo "$1; out <- .Last.value; write.table(file=stdout(), out, row.names=FALSE, col.names=FALSE); quit()" | /usr/local/bin/R --slave --no-save
You may also want to create your own method for returning/outputting
data. An ideal way for doing this is to use create a so called generic
function, say, returnOutput(), and then special functions for each class
of object that you might get returned, e.g. returnOutput.matrix(),
returnOutput.list(), etc. Don't forget returnOutput.default(). If you
do not understand what I'm talking about here, please read up on
S3/UseMethod in R documentation. It's all in there. Then you'll also
get a much deeper understanding of how print() (and R) works. Please
don't ask me to explain it on the mailing list.
Cheers
Henrik
># doR 'A <- matrix(rnorm(100*5),c(100,5)); out <- chol(cov(A))'
>1.08824564637869 0.00749462665482204 -0.109577665309141 0.123824503621501 0.0420504647142321
>0 0.969304154505745 0.0689085053799411 0.143273894584171 -0.0204348333174425
>0 0 0.995383836907855 0.0860782051613422 0.056980680914183
>0 0 0 0.94180592438191 0.0534651651371964
>0 0 0 0 0.907266109886987
>
>Now we've got it!!
>
>The output above is nice and compact, and it doesn't have an extra
>newline, but if you want it to look nice on the screen, my friend Stephen
>Montgomery-Smith (Math, U Missouri) made me this nice little perl script
>for aligning numbers neatly and easily (but it doesn't work if there are
>letters in there (e.g., NA or 1.3e-6):
>
>http://taxa.epi.umn.edu/misc/numalign
>
># ./doR 'A <- matrix(rnorm(100*5),c(100,5)); out <- chol(cov(A))' | numalign
>0.903339952680364 -0.088773840144205 -0.223677935069773 -0.0736286093726908 0.0457396703130186
>0 1.08096548052082 0.0800540640587432 -0.0457840266135511 -0.0311210293661459
>0 0 0.93834307353671 0.0665017259723313 -0.0825698771035788
>0 0 0 1.03303581434252 0.118372967026342
>0 0 0 0 0.972768611955302
>
>Thanks very much for all of the help!!!
>
>Mike
>
>
>
More information about the R-help
mailing list