UPDATE: Thanks to Joshua's comment I realized the problem wasn't being inside a function, but inside a script. So I've edited the question and also provided my own answer.
When I use plot.xts() interactively it pops up a graphics window. I just tried it from inside a function (I'm troubleshooting a unit test and wanted some visual help) but nothing appeared. Aha, says I, I know the trick, just use print.
But print(plot.xts(x)) still shows no chart and instead prints my xts object! I.e. it does exactly the same as print(x).
The script I use to run unit tests is:
#!/usr/bin/Rscript --slave
library('RUnit')
options(warn=2) #Turn warnings into errors
#By naming the files runit.*.R, and naming the functions test*(), we can use
# all the defaults to defineTestSuite().
#NOTE: they have a weird default random number generator, so changed here
# to match the R defaults instead.
test.suite=defineTestSuite('tests',dirs=file.path('tests'),
rngKind = "Mersenne-Twister", rngNormalKind = "Inversion")
test.result <- runTestSuite(test.suite)
printTextProtocol(test.result)
The script below does two things:
plot to a device file, as you would in headless setting such as a webserver,
plot a screen device, I use x11() but you could use win().
There is no limitation imposed by Rscript. And this has nothing to do with xts as you could just as easily plot an xts object.
#!/usr/bin/Rscript
set.seed(42)
x <- cumsum(rnorm(100))
png("/tmp/darren.png")
plot(x)
dev.off()
x11()
plot(x)
Sys.sleep(3) # could wait for key pressed or ...
You cannot use graphics (or input functions like readline) when using RScript. However an RScript is still just R, so when you want to add something interactive (e.g. for troubleshooting) start R, then type:
source('run_tests.R')
When run this way, a line like this shows the chart:
plot(x$High);cat("Press a key");readline()
When run directly from the commandline with ./run_tests.R that line gets quietly ignored.
Related
I am trying to run an R script from the Windows command prompt (the reason is that later on I would like to run the script by using VBA).
After having set up the R environment variable (see the end of the post), the following lines of code saved in R_code.R work perfectly:
library('xlsx')
x <- cbind(rnorm(10),rnorm(10))
write.xlsx(x, 'C:/Temp/output.xlsx')
(in order to run the script and get the resulting xlsx output, I simply type the following command in the Windows command prompt: Rscript C:\Temp\R_code.R).
Now, given that this "toy example" is working as expected, I tried to move to my main goal, which is indeed very similar (to run a simple R script from the command line), but for some reason I cannot succeed.
Again I have to use a specific R package (-copula-, used to sample some correlated random variables) and export the R output into a csv file.
The following script (R_code2.R) works perfectly in R:
library('copula')
par_1 <- list(mean=0, sd=1)
par_2 <- list(mean=0, sd=1)
myCop.norm <- ellipCopula(family='normal', dim=2, dispstr='un', param=c(0.2))
myMvd <- mvdc(myCop.norm,margins=c('norm','norm'),paramMargins=list(par_1,par_2))
x <- rMvdc(10, myMvd)
write.table(x, 'C:/Temp/R_output.csv', row.names=FALSE, col.names=FALSE, sep=',')
Unfortunately, when I try to run the same script from the command prompt as before (Rscript C:\Temp\R_code2.R) I get the following error:
Error in FUN(c("norm", "norm"))[[1L]], ...) :
cannot find the function "existsFunction"
Calls: mvdc -> mvdcCheckM -> mvd.has.marF -> vapply -> FUN
Do you have any idea idea on how to proceed to fix the problem?
Any help is highly appreciated, S.
Setting up the R environment variable (Windows)
For those of you that want to replicate the code, in order to set up the environment variable you have to:
Right click on Computer -> Properties -> Advanced System Settings -> Environment variables
Double click on 'PATH' and add ; followed by the path to your Rscript.exe folder. In my case it is ;C:\Program Files\R\R-3.1.1\bin\x64.
This is a tricky one that has bitten me before. According to the documentation (?Rscript),
Rscript omits the methods package as it takes about 60% of the startup time.
So your better solution IMHO is to add library(methods) near the top of your script.
For those interested, I solved the problem by simply typing the following in the command prompt:
R CMD BATCH C:\Temp\R_code2.R
It is still not clear to me why the previous command does not work. Anyway, once again searching into the R documentation (see here) proves to be an excellent choice!
I would like to be able to modify a hidden function inside an R package in an "automated" way, like using fixInNamespace, but where I can write the code in advance, and not in an "edit" window which fixInNamespace does. I think assignInNamespace could do the job, but currently it's not working. Here's an example of the problem.
require(quantmod)
getSymbols("AAPL")
chartSeries(AAPL) # Works fine up to here.
Now say I want to yaxis ticks to be drawn on the left side of the plot, instead of the right. This can be done by modifying the source code in the quantmod package. The relevant code for modifying the plot layout is in a hidden quantmod function called chartSeries.chob.
This could be done by doing this:
fixInNamespace("chartSeries.chob", ns = "quantmod")
and in the edit window, manually modify line 117 from axis(4) to axis(2), click OK, and again run chartSeries(AAPL) (now the y axis labels will plot on the left side of the plot). Everything is good, the plot is generated as expected, no problems.
But ... now suppose I want to modify chartSeries.chob in advance (in an automated way), presumably by sourcing a modified version of the chartSeries.chob function, without using the edit window. I might want modify dozens of lines in the function for example, and opening the edit window each time for a new R session is not practical.
How can I do this?
Right now I am doing this, which is not working:
assignInNamespace("chartSeries.chob", value = chartSeries.chob2, ns = "quantmod")
where I source from the console a full copy of chartSeries.chob with the modified code on line 117.
chartSeries.chob2 <- function (x)
{
old.par <- par(c("pty", "mar", "xpd", "bg", "xaxs", "las",
"col.axis", "fg"))
on.exit(par(old.par))
....
[Edit On 117:] axis(2)
...
}
When I run from the console:
chartSeries(AAPL)
or
quantmod:::chartSeries(AAPL)
I get errors -- the calls to other functions in quantmod from within the chartSeries.chob function are not found, presumably because the edited chartSeries.chob function is not in the quantmod namespace?
I notice that when typing quantmod:::chartSeries.chob from the console after the assignInNamespace command, there is no environment: namespace:quantmod at the end of the function definition.
But if I do the fixInNamespace modification approach, when I type quantmod:::chartSeries.chob, then I do see environment: namespace:quantmod appended to the end of the function definition.
Since fixInNamespace calls assignInNamespace you should be able to get it to work, the problem is probably that the environment is not the same and possibly some other attributes. If you change those to match then I would expect it to work better, possibly using code like:
tmpfun <- get("chartSeries.chob", envir = asNamespace("quantmod"))
environment(chartSeries.chob2) <- environment(tmpfun)
attributes(chartSeries.chob2) <- attributes(tmpfun) # don't know if this is really needed
assignInNamespace("chartSeries.chob", chartseries.chob2, ns="quantmod")
Another option for some changes would be to use the trace function. This would make temporary changes and would be fine for inserting code, but I don't know if it would be reasonable for deleting commands or modifying in place (specifying an editor that changed the code rather than letting you change it might make this possible).
I need to execute some commands in batch mode (e.g., via Rscript). They work in interactive mode, but not in batch mode. Here is a minimal example: sapply(1:3, is, "numeric"). Why does this work in interactive mode but return an error in batch mode? Is there a way to make a command like this work in batch mode?
More specifically, I need to write scripts and to run them in batch mode. They need to call a function (which I didn't write and can't edit) that looks like this:
testfun <- function (...)
{
args <- list(...)
if (any(!sapply(args, is, "numeric")))
stop("All arguments must be numeric.")
else
writeLines("All arguments look OK.")
}
I need to pass a list to this function. A command like testfun(list(1, 2, 3)) works in interactive mode. But in batch mode, it produces an error: Error in match.fun(FUN) : object 'is' not found. I tried debugger() to get a handle on the problem, but it didn't give me any insight. I also looked through r-help, the R FAQ, R Inferno, but I couldn't find anything that spoke to this problem.
Rscript doesn't load the methods package by default because it takes a lot of time. From the Details section of ?Rscript:
‘--default-packages=list’ where ‘list’ is a comma-separated list
of package names or ‘NULL’. Sets the environment variable
‘R_DEFAULT_PACKAGES’ which determines the packages loaded on
startup. The default for ‘Rscript’ omits ‘methods’ as it
takes about 60% of the startup time.
You can make it load methods by using the --default-packages argument.
> Rscript -e 'sapply(1:3, is, "numeric")' --default-packages='methods'
[1] TRUE TRUE TRUE
If I edit a function with R v2.14.0 using fix(), those fixes are applied during the session.
For example, I might make the following edit to get a white background in a hive plot:
> library(HiveR)
> fix(plotHive)
... :%s/black/white/g
... :w
... :q
> plotHive(myHiveData)
I then get a white background in the hive plot, as expected.
But if I quit and reopen R, I have lost those changes, and the plot has a black background again.
How do I preserve the edits I make with fix() between R sessions?
EDIT
If I source() the modified plotHive() function, I get the following error:
> modifiedPlotHive <- source("modifiedPlotHive.R")
Error in source("modifiedPlotHive.R") :
modifiedPlotHive.R:1160:1: unexpected '<'
1159: }
1160: <
^
In addition: Warning message:
In readLines(file) : incomplete final line found on 'modifiedPlotHive.R'
The final line in the modified plotHive() function is:
<environment: namespace:HiveR>
If I remove this line before source()-ing, then the function no longer works.
Sorry I missed this when it came out, but the latest version of HiveR has the option to control the background color (available on CRAN 0.2-1) Bryan
Here's the safer way of doing what you want, referenced by #joran.
The sink/source pair is fine for dealing with R code files. But saving to text files and then reading back in other types of objects can strip them of important attributes, especially those relating to environments. That's what you just experienced.
The save/load pair stores objects in R's own binary format, so is much less liable to lose important information/environments attached to functions.
In this example, I define a personal version of ls, which differs from the base function in that it by default lists objects that start with a dot/period:
my_ls <- ls
fix(my_ls)
# 1) On the first line, change 'all.names=FALSE' to 'all.names=TRUE'
# 2) Say "Yes", I want to save the changes
save("my_ls", file="my_ls.Rdata")
# Then, in a later session, test that it works
load("my_ls.Rdata")
.TrysToHide <- 99
my_ls()
# [1] ".TrysToHide" "my_ls"
One more note: it's much cleaner to give your modified function a name of its own. To really edit a packaged function, and have the changes persist, you'd need to edit the sources and recompile the package. But if you do that, beware, as you may well break the function for other packaged functions that depend on it.
There are a couple of options:
Save your workspace before quiting and load it again when you reopen R.
Save the modified function to script file and source it:
sink("modified_plotHive.r")
plotHive
sink()
In the next session:
plotHive <- source("modified_plotHive.r")
HTH
I have a number of bash scripts which invoke R scripts for plotting things. Something like:
#!/bin/bash
R --vanilla --slave <<RSCRIPT
cat("Plotting $1 to $2\n")
input <- read.table("$1")
png("$2")
plot(as.numeric(input[1,]))
dev.off()
RSCRIPT
The problem is that despite --slave, the call to dev.off() prints the message null device 1. Once there are a lot of plots being done, or for more complex scripts which plot to a number of files, this gets to be a real hassle.
Is there some way to suppress this message?
For no good reason I'm aware of, dev.off(), unlike device related functions like png() returns a value: "the number and name of the new active device." That value is what's being echoed to stdout.
Suppressing it can thus be achieved by just putting it somewhere, i.e.,
garbage <- dev.off()
One of the nice things about R is that you can view the source of many functions:
> dev.off
function (which = dev.cur())
{
if (which == 1)
stop("cannot shut down device 1 (the null device)")
.Internal(dev.off(as.integer(which)))
dev.cur()
}
<environment: namespace:grDevices>
So it calls .Internal(dev.off(...)) and then returns dev.cur(), which I suppose would be useful if you have several devices open so you know which one became active. You could use .Internal(dev.off(as.integer(dev.cur()))) in your script, or even patch dev.off to only return the value of dev.cur() if it is something else than the null device, and send the patch to the maintainers of R.
Also, graphics.off() calls dev.off() for all devices and doesn't return anything.
Ran into the same issue recently and noticed that one more possibility is not mentioned in the answers here:
invisible(dev.off())
This will hide the output from dev.off() and will not create additional variables unlike assigning the output to garbage variable: garbage <- def.off() would.
Another option would be to use sink() and output everything to a log file, so you can check up on whether the plots worked if you need to.
You can use littler instead which is a) an easier way to write R 'scripts' and b) suppresses output so you get the side effect of dev.off being silent:
$ foo.r /tmp/foo.txt /tmp/foo.png
Plotting /tmp/foo.txt to /tmp/foo.png
$ cat /tmp/foo.r
#!/usr/bin/r
cat("Plotting", argv[1], "to", argv[2], "\n")
input <- read.table(argv[1])
png(argv[2])
plot(as.numeric(input[1,]))
dev.off()
$
Rscript will probably work too; I tend to prefer littler.