knitr adds an empty figure with ssplot from seqHMM package - r

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.

Related

drake readd function not working for plots

I'm trying to trouble shoot why Drake plots are not showing up with readd() - the rest of the pipeline seem's to have worked though.
Not sure if this is caused by minfi::densityPlot or some other reason; my thoughts are the later as it's also not working for the barplot function which is base R.
In the RMarkdown report I have readd(dplot1) etc. in the chunks but the output is NULL
This is the code I have in my R/setup.R file:
library(drake)
library(tidyverse)
library(magrittr)
library(minfi)
library(DNAmArray)
library(methylumi)
library(RColorBrewer)
library(minfiData)
pkgconfig::set_config("drake::strings_in_dots" = "literals") # New file API
# Your custom code is a bunch of functions.
make_beta <- function(rgSet){
rgSet_betas = minfi::getBeta(rgSet)
}
make_filter <- function(rgSet){
rgSet_filtered = DNAmArray::probeFiltering(rgSet)
}
This is my R/plan.R file:
# The workflow plan data frame outlines what you are going to do
plan <- drake_plan(
baseDir = system.file("extdata", package = "minfiData"),
targets = read.metharray.sheet(baseDir),
rgSet = read.metharray.exp(targets = targets),
mSetSq = preprocessQuantile(rgSet),
detP = detectionP(rgSet),
dplot1 = densityPlot(rgSet, sampGroups=targets$Sample_Group,main="Raw", legend=FALSE),
dplot2 = densityPlot (getBeta (mSetSq), sampGroups=targets$Sample_Group, main="Normalized", legend=FALSE),
pal = RColorBrewer::brewer.pal (8,"Dark2"),
dplot3 = barplot (colMeans (detP[,1:6]), col=pal[ factor (targets$Sample_Group[1:6])], las=2, cex.names=0.8, ylab="Mean detection p-values"),
report = rmarkdown::render(
knitr_in("report.Rmd"),
output_file = file_out("report.html"),
quiet = TRUE
)
)
After using make(plan) it looks like everything ran smoothly:
config <- drake_config(plan)
vis_drake_graph(config)
I am able to use loadd() to load the objects needed for one of these plots and then make the plots, like this:
loadd(rgSet)
loadd(targets)
densityPlot(rgSet, sampGroups=targets$Sample_Group,main="Raw", legend=FALSE)
But the readd() command doesn't work?
The output in the .html for dplot3 looks weird...
Fortunately, this is expected behavior. drake targets are return values of commands, and so the value of dplot3 is supposed to be the return value of barplot(). The return value of barplot() is actually not a plot. The "Value" section of the help file (?barplot) explains the return value.
A numeric vector (or matrix, when beside = TRUE), say mp, giving the coordinates of all the bar midpoints drawn, useful for adding to the graph.
If beside is true, use colMeans(mp) for the midpoints of each group of bars, see example.
So what is going on? As with most base graphics functions, the plot from barplot() is actually a side effect. barplot() sends the plot to a graphics device and then returns something else to the user.
Have you considered ggplot2? The return value of ggplot() is actually a plot object, which is more intuitive. If you want to stick with base graphics, maybe you could save the plot to an output file.
plan <- drake_plan(
...,
dplot3 = {
pdf(file_out("dplot3.pdf"))
barplot(...)
dev.off()
}
)

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()

addPanel() causes second plot in markdown

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:

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 - How to align code and plot side by side

is there a simple way (e.g., via a chunk option) to get a chunk's source code and the plot it produces side by side, as on page 8 (among others) of this document?
I tried using out.width="0.5\\textwidth", fig.align='right', which makes the plot correctly occupy only half the page and be aligned to the right, but the source code is displayed on top of it, which is the normal behaviour.
I would like to have it on the left side of the plot.
Thanks
Sample code:
<<someplot, out.width="0.5\\textwidth", fig.align='right'>>=
plot(1:10)
#
Well, this ended up being trickier than I'd expected.
On the LaTeX side, the adjustbox package gives you great control over alignment of side-by-side boxes, as nicely demonstrated in this excellent answer over on tex.stackexchange.com. So my general strategy was to wrap the formatted, tidied, colorized output of the indicated R chunk with LaTeX code that: (1) places it inside of an adjustbox environment; and (2) includes the chunk's graphical output in another adjustbox environment just to its right. To accomplish that, I needed to replace knitr's default chunk output hook with a customized one, defined in section (2) of the document's <<setup>>= chunk.
Section (1) of <<setup>>= defines a chunk hook that can be used to temporarily set any of R's global options (and in particular here, options("width")) on a per-chunk basis. See here for a question and answer that treat just that one piece of this setup.
Finally, Section (3) defines a knitr "template", a bundle of several options that need to be set each time a side-by-side code-block and figure are to be produced. Once defined, it allows the user to trigger all of the required actions by simply typing opts.label="codefig" in a chunk's header.
\documentclass{article}
\usepackage{adjustbox} %% to align tops of minipages
\usepackage[margin=1in]{geometry} %% a bit more text per line
\begin{document}
<<setup, include=FALSE, cache=FALSE>>=
## These two settings control text width in codefig vs. usual code blocks
partWidth <- 45
fullWidth <- 80
options(width = fullWidth)
## (1) CHUNK HOOK FUNCTION
## First, to set R's textual output width on a per-chunk basis, we
## need to define a hook function which temporarily resets global R's
## option() settings, just for the current chunk
knit_hooks$set(r.opts=local({
ropts <- NA
function(before, options, envir) {
if (before) {
ropts <<- options(options$r.opts)
} else {
options(ropts)
}
}
}))
## (2) OUTPUT HOOK FUNCTION
## Define a custom output hook function. This function processes _all_
## evaluated chunks, but will return the same output as the usual one,
## UNLESS a 'codefig' argument appeared in the chunk's header. In that
## case, wrap the usual textual output in LaTeX code placing it in a
## narrower adjustbox environment and setting the graphics that it
## produced in another box beside it.
defaultChunkHook <- environment(knit_hooks[["get"]])$defaults$chunk
codefigChunkHook <- function (x, options) {
main <- defaultChunkHook(x, options)
before <-
"\\vspace{1em}\n
\\adjustbox{valign=t}{\n
\\begin{minipage}{.59\\linewidth}\n"
after <-
paste("\\end{minipage}}
\\hfill
\\adjustbox{valign=t}{",
paste0("\\includegraphics[width=.4\\linewidth]{figure/",
options[["label"]], "-1.pdf}}"), sep="\n")
## Was a codefig option supplied in chunk header?
## If so, wrap code block and graphical output with needed LaTeX code.
if (!is.null(options$codefig)) {
return(sprintf("%s %s %s", before, main, after))
} else {
return(main)
}
}
knit_hooks[["set"]](chunk = codefigChunkHook)
## (3) TEMPLATE
## codefig=TRUE is just one of several options needed for the
## side-by-side code block and a figure to come out right. Rather
## than typing out each of them in every single chunk header, we
## define a _template_ which bundles them all together. Then we can
## set all of those options simply by typing opts.label="codefig".
opts_template[["set"]](
codefig = list(codefig=TRUE, fig.show = "hide",
r.opts = list(width=partWidth),
tidy = TRUE,
tidy.opts = list(width.cutoff = partWidth)))
#
A chunk without \texttt{opts.label="codefig"} set...
<<A>>=
1:60
#
\texttt{opts.label="codefig"} \emph{is} set for this one
<<B, opts.label="codefig", fig.width=8, cache=FALSE>>=
library(raster)
library(RColorBrewer)
## Create a factor raster with a nice RAT (Rast. Attr. Table)
r <- raster(matrix(sample(1:10, 100, replace=TRUE), ncol=10, nrow=10))
r <- as.factor(r)
rat <- levels(r)[[1]]
rat[["landcover"]] <- as.character(1:10)
levels(r) <- rat
## To get a nice grid...
p <- as(r, "SpatialPolygonsDataFrame")
## Plot it
plot(r, col = brewer.pal("Set3", n=10),
legend = FALSE, axes = FALSE, box = FALSE)
plot(p, add = TRUE)
text(p, label = getValues(r))
#
\texttt{opts.label="codefig"} not set, and all settings back to ``normal''.
<<C>>=
lm(mpg ~ cyl + disp + hp + wt + gear, data=mtcars)
#
\end{document}
I see 3 possibilities
for beamer presentations, I'd go for \begin{columns} ... \end{columns} as well.
If it is only one such plot: Minipages
Here I used a table (column code and column result). (This example is "normal" Sweave)
For all three, the chunk options would have include = FALSE, and the plot would "manually" be put to the right place by \includegraphics[]{}.
You can display the text in a 'textplot' from package PerformanceAnalytics or gplots.
(Little) downside: To my knowledge there is no Syntax highlighting possible.
Sample Code:
```{r fig.width=8, fig.height=5, fig.keep = 'last', echo=FALSE}
suppressMessages(library(PerformanceAnalytics))
layout(t(1:2))
textplot('plot(1:10)')
plot(1:10)
```

Resources