I recently had the pleasure of presenting at useR2018 about practical workflows with R. One of the things that I commented about was how to get data out of R into other software easily. The majority of my clients work with excel when dealing with data, and as such will need some of my outputs in excel so they can use them. Unfortunately R doesn’t natively provide the simplest techniques to do this.
A while back I saw someone talking about pushing data to the clipboard using utils::write.table()
. I explored this a little further and found a realy helpful Q&A on Stack Overflow here.
Off the back of this I created my own function for my personal package that allowed me to do this.
My needs were only to do this on a mac, so the function is quite simple and could be extended for other operating systems, but in it’s simplest form it looks like this.
copy_clip <- function(x, include_header = TRUE) {
utils::write.table(x,
pipe("pbcopy"),
sep = "\\t",
row.names = FALSE,
col.names = include_header)
}
My recent challenge came when I decided to start using RStudio Server. My copy_clip()
function would no longer work. The key reason is because the output of the function was being pushed to the servers clipboard. I quickly went to twitter and had my concerns confirmed… it wasn’t looking like my function would work any more.
This is a fairly critical part of my workflow so I wanted to find a solution that might work and so I took a step back and started to think about how to push a clipboard from the server to my local machine. I came across a couple of good Q&As.
- How to send data to local clipboard from a remote SSH session
- How to copy remote machines text to local machines clipboard through SSH?
With these I was able to work a solution that allows me to use copy_clip()
once again to get the output from R into my local machine, even when using RStudio Server.
The process.
This is how I did it on a mac, I’m sure with a little searching you’d be able to find suitable instructions for how to do this on a different local operating system.
1. Turn on remote sharing in system preferences
Within system preferences go to the sharing menu and turn on remote login Remote Login
2. Create an ssh key for the server machine
Digital Ocean has a really easy to follow instruction here. The key thing to remember is you’re creating the ssh key on your RStudio Server and then transferring the it to your local machine. So when you get to Step 2 in the instructions, make sure you use the IP address of the local machine.
3. Set your local machine to have a static IP (optional, but very useful)
If you have the ability to, it is worth setting up your local machine to have a static IP address, that way when you want to copy from the server you won’t have to check your IP every time.
4. Update the copy_clip()
function
With the reverse SSH setup I updated the function that it will work from the RStudio server with the addition of the remote =
argument. The argument takes an ssh host eg username@remote_host
copy_clip <- function(x, include_header = TRUE, remote = NULL) {
if (is.null(remote)) {
utils::write.table(x, pipe("pbcopy"), sep = "\t",
row.names = FALSE, col.names = include_header)
} else {
utils::write.table(x, "tmp_dat", sep = "\t",
row.names = FALSE, col.names = include_header)
system(paste("cat tmp_dat | ssh", remote, "pbcopy"))
system("rm tmp_dat")
}
}
You’ll see that the write.table
function now actually creates a file on the server called ‘tmp_dat’ and then uses piping to push the contents of that file to the remote connection. To keep things nice too, it makes sure to remove the data file afterwards.
BIG CAVEAT
I am no security expert, and my pasting happens over my private network. My undrstanding is that SSH is quite secure, so I don’t see why there would be any issues in using this type of reverse SSH, however if you’re unsure I would consult with your neighbourhood security expert.