tags:

views:

328

answers:

8

For the purposes of teaching and preparing written instructions about R, one of the things that's always frustrated me is that I can't simply copy commands and output from R and paste them into another R session. For example, if I do something trivial, such as

> x <- rnorm(10)
> x
 [1]  1.76975998  1.19722850 -0.39274507 -1.10979974  0.52320473 -0.08643833
 [7]  0.94437690  0.08083207  0.62260363  1.89305469

If I copy and paste that into a document or even here in this post, you (and my students) can not then just highlight it, copy it and paste it into an R session successfully

> > x <- rnorm(10)
Error: syntax error
> > x
Error: syntax error
>  [1]  1.76975998  1.19722850 -0.39274507 -1.10979974  0.52320473 -0.08643833
Error: syntax error
>  [7]  0.94437690  0.08083207  0.62260363  1.89305469
Error: syntax error

You might want to do this to test your installation of R, compare my output to yours, or simply to make use of a function I've offered.

So, what I'd like to be able to do is to change the default prompt from > to either an empty string or a blank space and also prefix all output lines with a hash mark #. That way, I could use R interactively to generate a session that looks like

x <- rnorm(10)
x
# [1]  1.76975998  1.19722850 -0.39274507 -1.10979974  0.52320473 -0.08643833
# [7]  0.94437690  0.08083207  0.62260363  1.89305469

which could be copy/pasted into an R session successfully. It would make prepping R code for a journal article, students, lectures, etc. much easier for me (and maybe for others?)

I've poked around the documentation with no luck... any ideas? pointers?

Currently, I'm using R on a Mac either via the R.app GUI or from Terminal.

+2  A: 

As for changing the prompt, the command you're looking for is options, with argument prompt, which I found here.

> options(prompt = "# Customized R Prompt!\n")
# Customized R Prompt!
1 + 5
[1] 6
# Customized R Prompt!

Setting the prompt to an empty string results in:

> options(prompt="")
Error in options(prompt = "") : invalid value for 'prompt'

Which is why I used a comment. As far as I can tell, R does not have block comments, which is why I made the prompt a line comment and put a newline at the end of it -- should be no problems if anyone copy-pastes your session that way.

I'm still looking on the output format for a bit here... There's some code at this mailling list post that seems to format the output without the [#] blocks, but it's sure not pretty.

Mark Rushakoff
You're right that it needs to be a non-empty string... (wonder why they require that....), but a single space seems to work well: options(prompt=" ")
William Doane
+1  A: 

You write that

one of the things that's always frustrated me is that I can't simply copy commands and output from R and paste them into another R session.

and I presume you are on Windows with the standard R Windows binary. I fear that what you have in mind may just not be doable. But because what you want to do is actually very desirable, people have done in a different way. From the ESS manual:

5 Manipulating saved transcript files

Inferior S mode records the transcript (the list of all commands executed, and their output) in the process buffer, which can be saved as a "transcript file", which should normally have the suffix `.St'. The most obvious use for a transcript file is as a static record of the actions you have performed in a particular S session. Sometimes, however, you may wish to re-execute commands recorded in the transcript file by submitting them to a running ESS process. This is what Transcript Mode is for.

If you load file a with the suffix `.St' into Emacs, it is placed in S Transcript Mode. [...]

Switching to Emacs/ESS may however not be compatible with your students. So for directly copying and pasting, your best bet may just be to wrap expressions into dput() first:

R> set.seed(42)
R> x <- rnorm(10)
R> x
 [1]  1.37096 -0.56470  0.36313  0.63286  0.40427 -0.10612  1.51152 -0.09466  2.01842 -0.06271
R> dput(x)
c(1.37095844714667, -0.564698171396089, 0.363128411337339, 0.63286260496104, 
0.404268323140999, -0.106124516091484, 1.51152199743894, -0.0946590384130976, 
2.01842371387704, -0.062714099052421)
R>

The last expression can be cut and pasted back to R.

Dirk Eddelbuettel
+2  A: 

I have two other suggestions:

1) You could write your code in a script file; then you can copy and paste the code without any trouble.

From the standard R GUI, go File > New Script. Enter all your code in there, then to run it, just highlight code and press CTRL-R. Many other R GUI's have similar behavior. You can still work interactively in this mode; the key difference is that you highlight code and run it rather than hitting ENTER.

2) Use the history() functions. See the help: ?history. You can save your console history with this:

savehistory(file = ".Rhistory")

Then you can open it as a script file with this command:

edit(file=".Rhistory")

You might also want to change the max.show, possibly even as the default in your own .Rprofile. For example,

history(max.show = Inf, reverse = FALSE)

Shane
You're right. The problem with this approach is that when one is developing teaching examples, you're often even more "interactive" working with R than you are when doing straight data analysis. You're playing with features, options, output styles, etc. so much that the normal flow of the history is filled with noise, and you want to be able to extract just the right set of items from that session... I have spent a fair amount of time looking through history files, trying to find that one moment when I had the perfect series of examples... but it's a time sink, in my experience.
William Doane
That's a fair point. I usually find the history file to be very messy as well. In which case (assuming none of the other prompt adjustment answers work), I suggest just working from a script file and running it line by line. Find a GUI that's comfortable for you. It's very easy to experiment, and by the end you will have a complete R file to teach from. You can even go so far as to package your script: you will see several examples of stats courses on CRAN.
Shane
+5  A: 

You might try:

options(prompt=" ", continue=" ")

Note the spaces in between the quotes.

The first option makes the prompt disappear. The second erases the "+" from appearing on long wrapping lines.

Jake
This is a full half of the solution... I knew about the prompt option, but not the continue option... that helps, a lot.
William Doane
Now, if there were a prefixoutput option!
William Doane
+1  A: 

Not sure whether this is supported on all platforms, but on Windows, you can Copy, then right-click and select "Paste commands only", which does exactly what you need. Unfortunately, there's no keyboard shortcut.

Richie Cotton
Doesn't seem to be an option in R.app on Mac.... :(
William Doane
+1  A: 

There was a recent discussion on the r-help mailing list with several example functions to strip > from pasted code to mimic the "Paste Commands Only" command of the Windows R GUI.

Kevin
+2  A: 

Painful way is to regexp an original output. Suppose you have some code:

x <- rnorm(10)
  x

head(USArrests)

lm(y~x+z,
    data.frame(y=rnorm(10),z=runif(10),x=rbinom(10,2,.5))
)

You can save it to a file and then using readLines read to variable. I do the same, using textConnection on copied output:

to_edit <- readLines(textConnection("
> x <- rnorm(10)
>   x
 [1] -0.43409069 -1.05399275  1.53440218  0.05812936  1.62713995 -1.20644184
 [7] -0.15698798 -2.36494897 -0.14440292  1.47182117
> 
> head(USArrests)
           Murder Assault UrbanPop Rape
Alabama      13.2     236       58 21.2
Alaska       10.0     263       48 44.5
Arizona       8.1     294       80 31.0
Arkansas      8.8     190       50 19.5
California    9.0     276       91 40.6
Colorado      7.9     204       78 38.7
> 
> lm(y~x+z,
+ data.frame(y=rnorm(10),z=runif(10),x=rbinom(10,2,.5))
+ )

Call:
lm(formula = y ~ x + z, data = data.frame(y = rnorm(10), z = runif(10),     x = rbinom(10, 2, 0.5)))

Coefficients:
(Intercept)            x            z  
    -0.6460       0.3678       0.3918  
"))

Now some edits:

id_commands <- grep("^> |^\\+ ",to_edit) # which are commands or its continuity
to_edit[id_commands] <- sub("^> |^\\+ ","",to_edit[id_commands]) # remove promt
to_edit[-id_commands] <- paste("#",to_edit[-id_commands]) # comment output

And the result is:

> writeLines(to_edit) # you can specify file or write on screen
# 
x <- rnorm(10)
  x
#  [1] -0.43409069 -1.05399275  1.53440218  0.05812936  1.62713995 -1.20644184
#  [7] -0.15698798 -2.36494897 -0.14440292  1.47182117

head(USArrests)
#            Murder Assault UrbanPop Rape
# Alabama      13.2     236       58 21.2
# Alaska       10.0     263       48 44.5
# Arizona       8.1     294       80 31.0
# Arkansas      8.8     190       50 19.5
# California    9.0     276       91 40.6
# Colorado      7.9     204       78 38.7

lm(y~x+z,
data.frame(y=rnorm(10),z=runif(10),x=rbinom(10,2,.5))
)
# 
# Call:
# lm(formula = y ~ x + z, data = data.frame(y = rnorm(10), z = runif(10),     x = rbinom(10, 2, 0.5)))
# 
# Coefficients:
# (Intercept)            x            z  
#     -0.6460       0.3678       0.3918  
#

It works but as I said it's painful.

Marek
This leads me to a pretty workable solution, which I'll have to post as an "answer", since the comments don't handle code formatting or long posts well. See my cleanCode() function, elsewhere in this thread... it's a direct riff on Marek's solution.
William Doane
+4  A: 

So, I very much like Jake and Marek's solutions. Jake's is straightforward, but doesn't address the output formatting part of the problem. Marek's was a bit cumbersome, so I wrapped it up in a function resulting in

cleanCode <- function() {
  if (.Platform$OS.type == "unix" && .Platform$pkgType == "mac.binary") {
    to_edit <- readLines(pipe("pbpaste")) # Mac ONLY solution
  } else {
    to_edit <- readLines("clipboard") # Windows/Unix solution
  }
  opts <- options()
  cmdPrompts <- paste("^", opts$prompt, "|^", opts$continue, sep="")

  # can someone help me here? how to escape the + to \\+, as well as other special chars

  id_commands <- grep("^> |^\\+ ", to_edit) # which are command or continuation lines
  to_edit[id_commands] <- sub("^> |^\\+ ", "", to_edit[id_commands]) # remove prompts
  to_edit[-id_commands] <- paste("  # ", to_edit[-id_commands]) # comment output
  writeLines(to_edit)
}

which lets me highlight and copy a portion of the interactive session.

So, for example, I can use this to copy

> x <- rnorm(20)
> plot(x)
> summary(x)
    Min.  1st Qu.   Median     Mean  3rd Qu.     Max. 
-2.34000 -0.86010 -0.21940 -0.43340  0.04383  1.06400 
> str(x)
 num [1:20] -1.568 -0.219 -1.951 1.064 0.768 ...
> sd(x)
[1] 0.8932958

to the clipboard and with a simple call to

> cleanCode()

produces output such as

x <- rnorm(20)
plot(x)
summary(x)
  #      Min.  1st Qu.   Median     Mean  3rd Qu.     Max. 
  #  -2.34000 -0.86010 -0.21940 -0.43340  0.04383  1.06400 
str(x)
  #   num [1:20] -1.568 -0.219 -1.951 1.064 0.768 ...
sd(x)
  #  [1] 0.8932958

which someone could quickly highlight and copy & paste into an R session to execute the code and compare their output. Of course, in this case, they'll get different results, since I'm basing the example on random data.

Thank you Jake, Marek, and everyone else... all of the responses have been helpful!

William Doane
I like it. It is a good idea to use a function. For Windows (and for Ubuntu too) in first line should be: to_edit <- readLines("clipboard")
Marek