Edit function in R and save changes (matlab-style)? - r

I have some R files containing functions I wrote. I source those files to have the functions available. If foo is my function and I type:
foo <- edit(foo)
or
fix(foo)
I can change the function and save it just for this session. How can I do the changes permanent, i.e. that they are saved in the source file? So far I am searching for the source file, edit it and then resource it, which can be annoying sometimes. I've seen it in Matlab, that "edit(function)" saves the changes in the source-file of the function.
thanks

I think it depends on what GUI (and hence what OS) you're running R in. Personally, I'm happy with R.app in OSX, but there are R-plugins for many common editors such as TextWrangler or Scite. IIRC these plugins allow you to execute "source" command from the editor so that saving your edits will also update the version of the function in your R-console environment.

Will saving the function object work for you? If so, use save() on the edited function and load() to load it back it. edit() and fix() are working with the parsed R objects, not the original files so it will be difficult or a pain to deparse them again
> foo <- function(x) 1:10
> writeLines("foo.txt", foo)
> writeLines(deparse(foo), "foo.txt")
> readLines("foo.txt")
[1] "function (x) " "1:10" ## not what is wanted
As #CarlWitthoft says, you might be better off using one of the many GUI and IDEs available for R. RStudio is very popular and user-friendly and Emacs + ESS is hard to beat.

Related

How to manage R extension / package documentation with grace (or at least without pain)

Now and then I embrace project specific code in R packages. I use the documentation files as suggested by Writing R Extensions to document the application of the code.
So once you set up your project and did all the editing to the .Rd files,
how do you manage a painless and clean versioning without rewriting or intense copy-pasting of all the documentation files in case of code or, even worse, code structure changes?
To be more verbose, my current workflow is that I issue package.skeleton(), do the editing on the .Rd-files followed by R CMD check and R CMD build. When I do changes to my code I need to redo the above maybe appending '.2.0.1' or whatever in order to preserve the precursor version. Before running the R CMD check command I need to repopulate all the .Rd-files with great care in order to get a clean check and succsessful compilation of Tex-files. This is really silly and sometimes a real pain, e.g. if you want to address all the warnings or latex has a bad day.
What tricks do you use? Please share your workflow.
The solution you're looking for is roxygen2.
RStudio provides a handy guide, but briefly you document your function in-line with the function definition:
#' Function doing something
#' Extended description goes here
#' #param x Input foo blah
#' #return A numeric vector length one containing foo
myFunc <- function(x) NULL
If you're using RStudio (and maybe ESS also?) the Build Package command automagically creates the .Rd files for you. If not, you can read the roxygen2 documentation for the commands to generate the docs.

Restart R within Rstudio

I'm trying to call a simple python script from within R using system2(). I've read some information I found vague that said if 'too much' memory is used, it won't work.
If I load a large dataset and use some information in it to use as arguments to pass into system2(), it will only work if I manually click "Restart R" in call Rstudio.
What I want:
df <- read.csv('some_large_file.csv')
###extracting some info called 'args_vec'
for(arg in args_vec){
system2('python', args)
}
This won't work as is. The for loop is simply passed over.
What I need:
df <- read.csv('some_large_file.csv')
###extracting some info called 'args_vec'
###something that 'restarts' R
for(arg in args_vec){
system2('python', args)
}
This answer doesn't quite get what I want. Namely, it doesn't work for me within Rstudio and it calls "system" (which presents the same problem as "system2" in this case). In fact, when I put the answer referenced above in my Rprofile.site file, it just immediately closed rstudio:
I tried the suggestion as a normal function (rather than using "makeActiveBinding", and it didn't quite work.
##restart R in r session -- doesn't work
makeActiveBinding("refresh", function() { system("R --save"); q("no") }, .GlobalEnv)
##nor did this:
refresh <- function() { system("R --save"); q("no") }
I tried a number of variations of these two options above, but this is getting long for what feels like a simple question. There's a lot I don't yet understand about the startup process and "makeActiveBinding" is a bit mysterious. Can anyone point me in the right direction?
In Rstudio, you can restart the R session by:
command/ctrl + shift + F10
You can also use:
.rs.restartR()
RStudio has this undocumented rs.restartR() which is supposed to do just that: restarting R.
However, it does not unload the packages that were loaded, nor does it clean the environment, so that I have some doubts about if it restarts R at all.
If you use RStudio, use the menu item Session > Restart R or the associated keyboard shortcut Ctrl+Shift+F10 (Windows and Linux) or Command+Shift+F10 (Mac OS). Additional keyboard shortcuts make it easy to restart development where you left off, i.e. to say “re-run all the code up to HERE”:
In an R script, use Ctrl+Alt+B (Windows and Linux) or Command+Option+B (Mac OS)
In R markdown, use Ctrl+Alt+P (Windows and Linux) or Command+Option+P (Mac OS)
If you run R from the shell, use Ctrl+D or q() to quit, then restart R.
Have you tried embedding the function call within the apply function, rather than a for loop?
I've had some pieces of code that ran the system out of memory in a for loop run perfectly with apply. It might help?
For those not limited to a command that want something that actually resets the system (no prior state, no loaded packages, no variables, etc.) you can select Terminate R from the Session menu.
It is a bit awkward (asks you if you are sure). If anyone knows something like clear all or really clear classes in MATLAB let me know!

Make a user-created function in R

I'm sorry if this has been asked before but I can't find the answer.
Let's say I write a small function in R
add2<-function(a){
return(a+2)
}
I save it as add2.R in my home directory (or any directory). How do I get R to find it??
> add2(4)
Error: could not find function "add2"
I know I can open up the script, copy/paste it in the console, run it, and then it works. But how do I get it built-in so if I open and close R, it still runs without me copying and pasting it in?
One lightweight option:
dump("add2", file="myFunction.R")
## Then in a subsequent R session
source("myFunction.R")
An alternative:
save("add2", file="myFunction.Rdata")
## Then just double click on "myFunction.Rdata" to open
## an R session with add2() already in it
## You can also import the function to any other R session with
load("myFunction.Rdata")
Until you're ready to package up functions into your own private package, storing them in well organized, source()-ready text files (as in the 1st example above) is probably the best strategy. See this highly up-voted SO question for some examples of how experienced useRs put this approach into practice.
Before invoking the function (e.g. at the beginning of the script), you should source the file containing your user defined function/s, i.e. :
source("add2.R") # this executes add2.R script loading add2 function
Basically, source function executes the code included in the script passed as argument. So if the file contains only functions definitions it loads the function in memory for future use.
If you want to start it automatically, then you have to set-up startup script and then use one of the methods outlined in answers above.
/Library/Frameworks/R.framework/Versions/2.15/Resources/etc/
is(for mac) the location of Rprofile.site, which must be edited adequately.
My version of it is:
.First <- function()
{
dir='~/Desktop/Infobase/R/0_init/0_init.R'
if(file.exists(dir))
{
source(dir, chdir = TRUE)
} else {cat("startup file is not found at:",dir)}
cat("\nWelcome at", date(), "\n")
}
.Last <- function()
{
cat("\nGoodbye at ", date(), "\n")
}
Note, that after you have sourced 1 R script, you do not need to enter this file anymore. Just do all you need from the file you sourced. In my case file "0_init.R" contains no functions, it just contains loading of other scripts. Well, you've got the idea.
Also, if you are doing this I recommend you to store them in new environment. Actual environments are not really suitable for your own functions(They are better implemented if you have a package developed, otherwise you lose a lot of control).
use "attach", "detach", "search", etc....
attach(FUN,name="af2tr")

Starting R and calling a script from a batch file

I have an R-based GUI that allows some non-technical users access to a stats model. As it stands, the users have to first load R and then type loadGui() at the command line.
While this isn't overly challenging, I don't like having to make non-technical people type anything at a command line. I had the idea of writing a .bat file (users are all running Windows, though multi-platform solutions also appreciated) that starts R GUI, then autoruns that command.
My first problem is opening RGui from the command line. While I can provide an explicit path, such as
"%ProgramW6432%\R\R-2.15.1\bin\i386\Rgui.exe"
it will need updating each time R is upgraded. It would be better to retrieve the location of RGui from the %path% environment variable, but I don't know an easy way to parse that.
The second, larger problem is how to call commands for R on startup from the command line. My first thought is that I could take a copy of ~/.Rprofile, append the extra command, and then replace the original copy of the file once R is loaded. This is awfully messy though, so I'd like an alternative.
Running R in batch mode isn't an option, firstly since I can't persuade GUIs to display themselves, and secondly because I would like the R console available, even if the users shouldn't need to use it.
If you want a toy GUI to test your ideas, try this:
loadGui <- function()
{
library(gWidgetstclck)
win <- gwindow("test")
rad <- gradio(letters[1:3], cont = win)
}
Problem 1: I simply do not ever install in the suggested default directory on Windows, but rather group R and a few related things in, say, c:/opt/ where I install R itself in, say,c:/opt/R-current so that the path c:/opt/R-current/bin will remain constant. On upgrade, I first renamed to R-previous and then install into a new R-current.
Problem 2: I think I solved that many moons ago with scripts. You can now use Rscript.exe to launch these, and there are tcltk examples for waiting for a prompt.
I have done similar a couple of times. In my cases the client was using windows so I just installed R on their computer and created a shortcut on their desktop to run R. Then I right click on the shortcut and choose properties to get the propertiest dialog. I then changed the "Start in" folder to the one where I wanted it to run from (which had the .Rdata file with the correct data and either a .First function in the .Rdata file or .Rprofile in the folder). There is also a "Run:" option that has a "Minimized" option to run the main R window minimized.
I had created the functions that I wanted to run (usually a specialized gui using tcltk) and any needed data and saved them in the .Rdata file and also either created .First or .Rprofile to run the comnand that showed the gui. The user double clicks on the icon on the desktop and up pops my GUI that they can work with while ignoring the other parts.
Take a look at the ProjectTemplate library. It does what you want to do. It loads used libraries from a batch file an run R files automatically after loading as well as a lot of other usefull stuff as well...
Using the answer from https://stackoverflow.com/a/27350487/41338 and a comment from Richie Cotton above I have arrived at the following solution to keeping a script alive until a window is closed by checking if the pointer to the window is valid.
For a RGtk2 window created and shown using:
library(RGtk2)
mainWindow <- gtkWindow("toplevel", show = TRUE)
Create a function which checks if the pointer to it exists:
isnull <- function(pointer){
a <- attributes(pointer)
attributes(pointer) <- NULL
out <- identical(pointer, new("externalptr"))
attributes(pointer) <- a
return(out)
}
and at the end of your script:
while(!isnull(mainWindow)) Sys.sleep(1)

Calling R from S-Plus?

Does anyone have any suggestions for a good way to call R from S-Plus? Ideally I would like to just pass code to R and get data back without having to write anything too elaborate to integrate them.
I should add that I'm familiar with the RinS package on Omegahat, but I haven't used it. I was under the impression that Insightful had made an effort to integrate the environments before Tibco took over.
Edit: It turns out that RinS doesn't work on Windows. I found that the easiest solution was to just use Rscript. I can call this from S-Plus with the system() command. For example, here's a simple script:
#! Rscript --vanilla --default-packages=utils
args <- commandArgs(TRUE)
print(args)
print(1:100)
Sys.sleep(2)
res <- "hello world"
class(res) <- "try-error"
if(inherits(res, "try-error")) q(status=1) else q()
And calling it from S-Plus:
system("rscript c://test.rscript 'some text'")
Then I just store the results into a text file and import it into S-Plus after the script is run.
RSPlus is the only option i'm aware of. I used it almost daily for about a year, but haven't used it since R 2.7. From your Q, it seems like you just want to run R inside SPlus, which RSPlus can certainly do (R is a separate interpreter accessible via an interface comprised of a few SPlus functions, the most-often used is '.R()', e.g., .R("fivenum", 1:10).
I think we are talking about the same thing though, because 'RinS' is one of two modules (SpinR being the other) that together comprise RSPlus (i.e., there's only a single interface, regardless of the direction you want to go--R to SPlus, or SPllus to R). Although it wasn't obvious to me at the time, i had to install both modules to get RinS to work.

Resources