addPanel() causes second plot in markdown - r

I'm using R 3.4.3 and the latest knitr to create a markdown document. I created a time series plot with moving average in an ordinary R script like this:
plot(xts.qty_ordered.by_day, col = 'red', main = 'Qty Ordered by Day')
addPanel(rollmean, k=20, on=1, col = 'blue')
and it gives me the time series with the moving average superimposed. When I put it in the Rmd document and knit it, however, the output contains two plots: the first is the time series alone, and the second is the time series with the moving average superimposed. How can I make knitr R not double up the output like this?

One possibility is to wrap the first plot within invisible in your Rmd document.
For example:
```{r}
library(xts);
data(sample_matrix)
sample.xts <- as.xts(sample_matrix)
invisible(plot(sample.xts[,"Close"]));
addPanel(rollmean, k = 20, on = 1, col = "blue");
```
Knitting produces:

Related

Quantmod addMACD() remove line plot

I was currently using Quantmod to visualize technical analysis of equity data. When I came across the addMACD() functions for adding MACD graph and it works fine, except when I need to visualize the histogram only instead of the line graph.
addMACD(fast = display$macdFast, slow = display$macdSlow, signal = display$macdSignal, histogram = TRUE)
After reading through the documentation, I cannot figure out a way to remove the line plot of MACD graph. Is is possible to remove line plot while retaining histogram plot for MACD?
I always seem have problems with creating complicated newTA objects with quantmod, but here is an SO example. I find it easier to use rtsplot. That is a plotting package for xts objects but based on the base plots.
Since the macd histogram is nothing but the difference between the macd and the macd signal you can create your own histogram values:
library(quantmod)
goog <- getSymbols("GOOGL", from = "2019-01-01", auto.assign = F)
goog_macd <- MACD(goog$GOOGL.Close)
goog_macd_his <- goog_macd$macd - goog_macd$signal
library(rtsplot)
layout(c(1,1,1,2))
rtsplot(goog, type = "candle")
rtsplot(goog_macd_his , type = "h", lwd = 2)

Save automatically produced plots in R

I'm using a function in R able to analyse my data and produce several plots.
The function is "snpzip" from adegenet package.
I would like to save automatically the three plots that the function produces as part of the output. Do you have any suggestion on how to do it?
I want to point to the fact that I know how to save a single plot, for instance with png or pdf followed by dev.off(). My problem is that when I run snpzip(snps, phen, method = "centroid"), the outcomes are three plots (which I would like to save).
I report here the same example as in the "adegenet" package:
simpop <- glSim(100, 10000, n.snp.struc = 10, grp.size = c(0.3,0.7),
LD = FALSE, alpha = 0.4, k = 4)
snps <- as.matrix(simpop)
phen <- simpop#pop
outcome <- snpzip(snps, phen, method = "centroid")
If you use a filename with a C integer format in it, then R will substitute the page number for that part of the name, generating multiple files. For example,
png("page%d.png")
plot(1)
plot(2)
plot(3)
dev.off()
will generate 3 files, page1.png, page2.png, and page3.png. For pdf(), you also need onefile=FALSE:
pdf("page%d.pdf", onefile = FALSE)
plot(1)
plot(2)
plot(3)
dev.off()

Plotting tanglegrams subplots in R using dendextend

I am plotting Tanglegrams in R using dendextend. I am wondering if it is possible to plot multiple subplots using par(mfrow = c(2,2))?
I can't seem to figure it out.
Thanks
library(dendextend)
dend15 <- c(1:5) %>% dist %>% hclust(method = "average") %>% as.dendrogram
dend15 <- dend15 %>% set("labels_to_char")
dend51 <- dend15 %>% set("labels", as.character(5:1)) %>% match_order_by_labels(dend15)
dends_15_51 <- dendlist(dend15, dend51)
par(mfrow = c(2,2))
tanglegram(dends_15_51)
tanglegram(dends_15_51)
tanglegram(dends_15_51)
tanglegram(dends_15_51)
tl;dr: It is not possible to use par(mfrow=...) with the function tanglegram, but it is possible using layout.
Explanation: If you look closer at function tanglegram, you'll see (methods(tanglegram)) that, underneath, there are several methods, among which, dendextend:::tanglegram.dendrogram which is called to draw the tanglegram (as can be seen inside dendextend:::tanglegram.dendlist function).
Inside this function, there is a call to layout:
layout(matrix(1:3, nrow = 1), widths = columns_width)
This "erases" your previous setting of par(mfrow=c(2, 2)) and changes it to c(1, 3) (just for the "time" of the function though because at the end of the function, the value is reset...).
Indeed, in the help page of layout, it says:
These functions are totally incompatible with the other mechanisms for arranging plots on a device: par(mfrow), par(mfcol) and split.screen.
Conclusion: If you want to plot several tanglegrams in the same "window" you'll need to use the layout call (with 12 subparts: 2 rows and 6 columns) ahead of the calls to tanglegram and suppress the layout call inside tanglegram using the argument just_one=FALSE.
Example of drawing several tanglegrams:
Using the code below, you can then obtain the desired plot (I put the function's default widths for the layout):
layout(matrix(1:12, nrow=2, byrow=TRUE), widths=rep(c(5, 3, 5), 2))
tanglegram.dendlist_mod(dends_15_51, just_one=FALSE)
tanglegram.dendlist_mod(dends_15_51, just_one=FALSE)
tanglegram.dendlist_mod(dends_15_51, just_one=FALSE)
tanglegram.dendlist_mod(dends_15_51, just_one=FALSE)
This was done by updating the dendextend package in which: I modified the 2 functions tanglegram.dendrogram and tanglegram.dendlist to add a just_one parameter, which defaults to TRUE and changed the line of the layout in tanglegram.dendrogram to:
if (just_one) layout(matrix(1:3, nrow = 1), widths = columns_width)
I also suppressed the reset of par parameters and of course changed the call in tanglegram.dendlist (now called tanglegram.dendlist_mod) so it calls the new modified function, incorporates the just_one parameter and passes it to the modified tanglegram.dendrogram function.
Rather than creating a combined plot in a single graphical device, you could create multiple plots and arrange them when you put them in a document. The knitr package makes it easy to do this, by using fig.show = "hold" to hold on to multiple plots produced in a single R chunk and specifying a relevant out.width, e.g. 50% to have two plots in a row, for when the plots are placed in the document.
For example, in an R markdown (.Rmd) file you might have
```{r, fig.show = "hold", out.width = "50%", echo = FALSE}
suppressPackageStartupMessages(library(dendextend))
dend15 <- c(1:5) %>% dist %>% hclust(method = "average") %>% as.dendrogram
dend15 <- dend15 %>% set("labels_to_char")
dend51 <- dend15 %>% set("labels", as.character(5:1)) %>% match_order_by_labels(dend15)
dends_15_51 <- dendlist(dend15, dend51)
tanglegram(dends_15_51, margin_outer = 1)
plot.new()
tanglegram(dends_15_51, margin_outer = 1)
plot.new()
tanglegram(dends_15_51, margin_outer = 1)
plot.new()
tanglegram(dends_15_51, margin_outer = 1)
```
which when knitted to HTML, would look like the following:
There a few modifications I made to the code:
Suppressed package startup messages from dendextend.
Increased default margin_outer to avoid overlapping x axis labels from neighbouring plots.
Added plot.new() in between calls to tanglegram, otherwise the next plot would be drawn on top of the previous one (this is a result of tanglegram using layout and is not needed in general when producing multiple plots).
The same approach can be used in .Rnw files. If you are compiling to PDF (via LaTeX) you can add a figure caption and subcaptions, see knitr demo #067 - Graphics Options for more detail.

knitr adds an empty figure with ssplot from seqHMM package

I have the following chunk in RStudio:
<<sumfig,dependson='data',fig.cap="Summary of sequences">>=
ssplot(smult)
#
ssplot is a function in seqHMM package which creates a frequency graph and smult is my sequence data.
When I run my code, I get two figures in my pdf: The first one is an empty white figure with label {fig:sumfig1} and the second one is the real figure with label {fig:sumfig1}. I have similar experience with other plots from this package. I also have some other graphs in my file from other packages which work just fine.
Is it something wrong with the package or I am doing something wrong?
The root of this issue seems to be seqHMM:ssplot, not knitr: Even in an interactive sesion, ssplot generates two plots, an empty one and the actual plot.
If there is only one plot generated in the chunk with ssplot, the chunk option fig.keep = "last" can be used to disregard the first plot and show only the second (last) one.
\documentclass{article}
\begin{document}
<<echo = FALSE, message = FALSE, fig.keep = "last">>=
library(seqHMM)
# from ?ssplot
data("biofam3c")
# Creating sequence objects
child_seq <- seqdef(biofam3c$children, start = 15)
marr_seq <- seqdef(biofam3c$married, start = 15)
left_seq <- seqdef(biofam3c$left, start = 15)
## Choosing colors
attr(child_seq, "cpal") <- c("#66C2A5", "#FC8D62")
attr(marr_seq, "cpal") <- c("#AB82FF", "#E6AB02", "#E7298A")
attr(left_seq, "cpal") <- c("#A6CEE3", "#E31A1C")
# Plotting state distribution plots of observations
ssplot(list("Children" = child_seq, "Marriage" = marr_seq,
"Residence" = left_seq))
#
\end{document}
As of knitr 1.14 (the current development version, available on GitHub), you can also use fig.keep to specify which plots exactly you want to keep: fig.keep = c(1,3) will keep the first and the third plot.

r - Missing object when ggsave output as .svg

I'm attempting to step through a dataset and create a histogram and summary table for each factor and save the output as a .svg . The histogram is created using ggplot2 and the summary table using summary().
I have successfully used the code below to save the output to a single .pdf with each page containing the relevant histogram/table. However, when I attempt to save each histogram/table combo into a set of .svg images using ggsave only the ggplot histogram is showing up in the .svg. The table is just white space.
I've tried using dev.copy Cairo and svg but all end up with the same result: Histogram renders, but table does not. If I save the image as a .png the table shows up.
I'm using the iris data as a reproducible dataset. I'm not using R-Studio which I saw was causing some "empty plot" grief for others.
#packages used
library(ggplot2)
library(gridExtra)
library(gtable)
library(Cairo)
#Create iris histogram plot
iris.hp<-ggplot(data=iris, aes(x=Sepal.Length)) +
geom_histogram(binwidth =.25,origin=-0.125,
right = TRUE,col="white", fill="steelblue4",alpha=1) +
labs(title = "Iris Sepal Length")+
labs(x="Sepal Length", y="Count")
iris.list<-by(data = iris, INDICES = iris$Species, simplify = TRUE,FUN = function(x)
{iris.hp %+% x + ggtitle(unique(x$Species))})
#Generate list of data to create summary statistics table
sum.str<-aggregate(Sepal.Length~Species,iris,summary)
spec<-sum.str[,1]
spec.stats<-sum.str[,2]
sum.data<-data.frame(spec,spec.stats)
sum.table<-tableGrob(sum.data)
colnames(sum.data) <-c("species","sep.len.min","sep.len.1stQ","sep.len.med",
"sep.len.mean","sep. len.3rdQ","sep.len.max")
table.list<-by(data = sum.data, INDICES = sum.data$"species", simplify = TRUE,
FUN = function(x) {tableGrob(x)})
#Combined histogram and summary table across multiple plots
multi.plots<-marrangeGrob(grobs=(c(rbind(iris.list,table.list))),
nrow=2, ncol=1, top = quote(paste(iris$labels$Species,'\nPage', g, 'of',pages)))
#bypass the class check per #baptiste
ggsave <- ggplot2::ggsave; body(ggsave) <- body(ggplot2::ggsave)[-2]
#
for(i in 1:3){
multi.plots<-marrangeGrob(grobs=(c(rbind(iris.list[i],table.list[i]))),
nrow=2, ncol=1,heights=c(1.65,.35),
top = quote(paste(iris$labels$Species,'\nPage', g, 'of',pages)))
prefix<-unique(iris$Species)
prefix<-prefix[i]
filename<-paste(prefix,".svg",sep="")
ggsave(filename,multi.plots)
#dev.off()
}
Edit removed theme tt3 that #rawr referenced. It was accidentally left in example code. It was not causing the problem, just in case anyone was curious.
Edit: Removing previous answer regarding it working under 32bit install and not x64 install because that was not the problem. Still unsure what was causing the issue, but it is working now. Leaving the info about grid.export as it may be a useful alternative for someone else.
Below is the loop for saving the .svg's using grid.export(), although I was having some text formatting issues with this (different dataset).
for(i in 1:3){
multi.plots<-marrangeGrob(grobs=(c(rbind(iris.list[i],table.list[i]))),
nrow=2, ncol=1,heights=c(1.65,.35), top =quote(paste(iris$labels$Species,'\nPage', g,
'of',pages)))
prefix<-unique(iris$Species)
prefix<-prefix[i]
filename<-paste(prefix,".svg",sep="")
grid.draw(multi.plots)
grid.export(filename)
grid.newpage()
}
EDIT: As for using arrangeGrob per #baptiste's comment. Below is the updated code. I was incorrectly using the single brackets [] for the returned by list, so I switched to the correct double brackets [[]] and used grid.draw to on the ggsave call.
for(i in 1:3){
prefix<-unique(iris$Species)
prefix<-prefix[i]
multi.plots<-grid.arrange(arrangeGrob(iris.list[[i]],table.list[[i]],
nrow=2,ncol=1,top = quote(paste(iris$labels$Species))))
filename<-paste(prefix,".svg",sep="")
ggsave(filename,grid.draw(multi.plots))
}

Resources