I have an issue with knitr and ggplot2 in Latex. I am trying to create a dynamic document with knitr. All my plots are in ggplot2. Hear me out:
I created the Latex document
I opened it in R Studio and saved the TEX file as RNW file. Global and Project options: knitr.
I pasted the R script there like:
<<echo=FALSE>>=
knitr::opts_chunk$set(fig.path='graphs/',
echo=FALSE, warning=FALSE, message=FALSE)
#
<<>>=
library(ggplot2)
library(tidyverse)
#
<<plot1>>=
my_data1 <- read.csv(file.choose(), header=TRUE, sep=",")
plot1 <- ggplot(data=my_data1, aes(x = pos , y = sum)) +
geom_line(colour = 'black', size = 1) +
scale_y_continuous(trans = 'log10', limits = c(1,100)) +
theme_classic() +
labs (x = 'axis_name1', y = 'axis_name2') +
coord_cartesian(xlim = c(1219890,1220102)) +
#
Everything is going well, except the graph does not show when I press 'Compile PDF' or in the graphs directory. However when I select only the R code and run it everything is fine(as long as I add print()). I managed to use TikZ which works just fine but without creating a dynamic document. I thought it was possible to output the plot directly in the PDF document but for some reason ggplot2 does not work. Is there something that I am missing?
Thank you.
Related
Sort of new to R markdown. I define a function that makes a plot with ggplot2 in a separate .R file:
heatMapDevRatio <- function(glmnet_obj_list,alpha_seq,
plot_name){
grid <- matrix(NA,nr=1,ncol=3)
colnames(grid) = c('alpha','lambda','dev.ratio')
for(idx in 1:length(glmnet_obj_list)){
alpha = getAlpha(names(glmnet_obj_list)[idx])
temp_df = data.frame(alpha=alpha,
lambda=glmnet_obj_list[[idx]]$lambda,
dev.ratio=glmnet_obj_list[[idx]]$dev.ratio)
grid = rbind(grid,temp_df)
}
grid = grid[-1,]
ggplot(data = grid, aes(lambda, alpha)) +
geom_raster(aes(fill = dev.ratio), interpolate = TRUE) +
ggtitle(plot_name) +
xlab(expression(~lambda)) +
ylab(expression(~alpha))
}
Anyway, the function runs fine-- the output goes to the standard graphics device if I run it in interactive session, or wherever I direct it if use the function in a script.
The problem is when I run the function in an Rmd file after source()-ing the file with the function definition.
```{r heatmap 10yr,eval=T,echo=F,fig.height=4,fig.width=4,fig.cap='lkjafkd'}
heatMapDevRatio(fitted_mods_20yr[2:10],alpha_seq,'adfasfd')
```
The export to pdf works, but on the pdf I just have a reference to some weird directory that doesn't seem to exist after execution-- where the figure should be, I have this text:
![lkjafkd](cox_summary[exported]_files/figure-latex/heatmap 10yr-1.pdf)
Should I just write the image to a file and include it, or should I be redirecting the graphics output? I thought it should just work.
Do you think the problem is the command I'm using to weave?
Rscript -e "rmarkdown::render('cox_summary.Rmd', output_format = 'pdf_document', output_file = 'cox_summary[exported].pdf')"
The following is my .Rnw file:
\documentclass{article}
\begin{document}
<<myChunk>>=
options(warn = 2)
library(ggplot2)
library(directlabels)
data(BodyWeight,package="nlme")
BodyWeight$temp <- as.character(BodyWeight$Rat)
BodyWeight$temp[BodyWeight$temp == "4"] <- "HI₂"
p <- qplot(Time,weight,data=BodyWeight,colour=temp,geom="line")
direct.label(p,"first.qp")
#
\end{document}
The following is how I call knitr from R:
library(knitr)
# I have tryied this but doesn't make difference:
# pdf.options(encoding='ISOLatin2.enc')
knit("mwe_knitr.Rnw")
I get following as output:
> knit("mwe_knitr.Rnw")
processing file: mwe_knitr.Rnw
|...................... | 33%
ordinary text without R code
|........................................... | 67%
label: myChunk
Quitting from lines 5-13 (mwe_knitr.Rnw)
Error in grid.Call(L_convert, x, as.integer(whatfrom), as.integer(whatto), :
(converted from warning) conversion failure on 'HI₂' in 'mbcsToSbcs': dot substituted for <e2>
I tried solutions with encoding, such as posted here:
Rhtml: Warning: conversion failure on '<var>' in 'mbcsToSbcs': dot substituted for <var>
(I note in comment above exactly where I try the solution to that problem) but it did not seem to change nothing for me.
I am using R 3.3.1 and knitr package 1.13 on Ubuntu.
It looks like using the cairo_pdf device resolves this issue. In the setup chunk below, I set the device option to the cairo_pdf device (that's the line that begins option(device = ...) and the global chunk option dev to default to "cairo_pdf" (in the line that begins knitr::opts_chunk$set(...). This approach is discussed in the knitr documentation (see the section Encoding of Multibyte Characters) and in Issue #436.
I've made a few other changes:
Instead of "hard-coding" "HI₂" I've used the Unicode symbol for the subscripted 2, "\U2082".
Changed the plot call to "standard" ggplot rather than qplot.
Changed from calling directlabels after making the plot to calling geom_dl to add direct labels within the "standard" ggplot workflow.
Set the fontfamily within geom_dl. I found that the subscript 2 was rendered with some font families, but not others.
Changed the warn option to zero (the default) so that warnings won't be turned into errors. I just did this while I was testing the code, but it can, of course, be set back to 2 if desired.
The chunk myChunk1a creates the plot. The chunk myChunk1b creates basically the same plot, but in multiple versions, each using a different font family. In these versions, you can see that the subscript 2 is rendered with some font families, but not others. I'm not sure what determines this and the results may be different on your system.
\documentclass{article}
\begin{document}
<<setup, include=FALSE>>=
options(warn = 0)
options(device = function(file, width = 7, height = 7, ...) {
cairo_pdf(tempfile(), width = width, height = height, ...)
})
knitr::opts_chunk$set(echo = FALSE, message=FALSE, warning=FALSE, dev="cairo_pdf")
#
<<myChunk>>=
library(ggplot2)
library(directlabels)
library(gridExtra)
library(dplyr)
data(BodyWeight,package="nlme")
BodyWeight$temp <- as.character(BodyWeight$Rat)
BodyWeight$temp[BodyWeight$temp=="4"] = "HI\U2082"
# Change first value so that HI2 label is easily visible
BodyWeight$weight[BodyWeight$temp=="HI\U2082" & BodyWeight$Time==1] = 350
#
<<myChunk1a, fig.height=5>>=
ggplot(BodyWeight, aes(Time, weight, colour=temp)) +
geom_line() +
geom_dl(method=list("first.qp", fontfamily="Helvetica", cex=1), aes(label=temp)) +
theme_bw() +
ggtitle("Helvetica") +
guides(colour=FALSE)
#
<<myChunk1b, fig.height=11>>=
# Create several plots, each demonstrating a different font family for the labels
grid.arrange(grobs=lapply(c("Helvetica","Courier","Palatino","Times","Serif"), function(f) {
ggplot(BodyWeight, aes(Time, weight, colour=temp)) +
geom_line() +
geom_dl(method=list("first.qp", fontfamily=f, cex=1), aes(label=temp)) +
labs(x="") +
theme_bw() +
theme(plot.margin=unit(c(0,0,0,0), "lines"),
text=element_text(size=9)) +
ggtitle(f) +
guides(colour=FALSE)
}), ncol=1)
#
<<myChunk2, fig.height=5>>=
data(BodyWeight,package="nlme")
BodyWeight$temp <- as.character(BodyWeight$Rat)
# Change first value so that HI2 label is easily visible
BodyWeight$weight[BodyWeight$temp=="4" & BodyWeight$Time==1] = 350
# Set temp==4 to desired expression
BodyWeight$temp[BodyWeight$temp == "4"] <- paste(expression(HI[2]))
# Convert temp to factor to set order
BodyWeight$temp = factor(BodyWeight$temp, levels=unique(BodyWeight$temp))
qplot(Time, weight, data=BodyWeight, colour=temp, geom="line") +
guides(colour=FALSE) +
geom_text(data=BodyWeight %>% group_by(temp) %>%
filter(Time == min(Time)),
aes(label=temp, x=Time-0.5, y=weight), parse=TRUE, hjust=1) +
theme_bw()
#
\end{document}
Here's what the plot from myChunk1a looks like:
I have been creating ternary plots in R Markdown using the package ggtern. I am using R version 3.2.2 (2015-08-14) -- "Fire Safety" on Platform: x86_64-w64-mingw32/x64 (64-bit). I am working within R Studio Version 0.99.489.
I want to switch from printing each plot individually to using an embedded reactive script (inputSelect and renderPlot functions). However, using ggtern within renderPlot I get an error that the dataframe I am calling cannot be found. I've done a number of tests... (1) I can call the same dataframe to renderTable, (2) I can call the same dataframe to renderPlot with base plot function (just X & Y data, ignoring Z), but ggplot gives the same "object 'yourdata' cannot be found".
I've tried switching out of R Markdown to just write (and then call) a separate Shiny app, but that gives similar errors.
Can anyone explain what is going on and suggest a solution? I have a lot of these to make and my short-term fix is to run some code that loops ggtern to print the 100+ plots to png files and then use a reactive script to select and call the images. But this obviously is less than ideal! I could also try using the ternary plot options in packages compositions or robCompositions - but would prefer plotting with ggtern, if possible.
Below are the data and reactive code chunks from my R Markdown document. I've also published the entire document (https://kdvdecisionanalysis.shinyapps.io/WhyCantPlot) where you can see the various tests that work and don't work. Thanks!
```{r data.import}
# Here is a very small example of input data
triadR <- data.frame(NarrID = rep(1:5, 2), Var = c(rep("Important",5),rep("Law", 5)), X = c(14.15406, 58.15887, 11.79224, 53.37626, 24.08851, 17.53618, 21.94300, 8.92137, 49.28843, 58.15012), Y = c(74.24623, 24.49748, 18.96985, 24.49748, 52.63819, 69.22111, 58.66835, 32.53769, 33.54272, 14.94975), Z = c(11.59971, 17.34365, 69.23792, 22.12626, 23.27329, 13.24271, 19.38865, 58.54094, 17.16886, 26.90012), Ax = rep(0.5,10), Ay = rep(0.5, 10), DNA = rep(NA, 10))
triadR[3,3:5] = NA
triadQ <- data.frame(Var=c("Important", "Law"), Triad=c("People acted according to", "Justice was achieved through"), X = c("Intuition", "Reconciliation"), Y=c("Logic", "Revenge"), Z=c("Values", "Deterence"), Project=c(1,1))
triadQ
triadR
```
This is the plot that I want to make. The ggtern commands generate the correct plot outside of a Shiny renderPlot command.
```{r ggtern, echo=TRUE, fig.width=4}
inputPanel(
selectInput("Triad", "Which triad would you like to view?", levels(unique(triadQ$Triad)))
)
renderPlot({
library(ggtern)
varname <- as.character(triadQ[which(triadQ$Triad==input$Triad),triadQ$Var]$Var)
data_nas <- data.frame(triadR[which(triadR$Var==varname),])
ggtern(data = plotdata, aes(plotdata$X, plotdata$Y, plotdata$Z)) +
geom_density_tern(n = 200, aes(fill = ..level.., alpha = ..level..)) +
geom_point() +
theme_bw() +
labs(x="Stable",y="Emergent",z="Unstable",title="Fit Together") +
scale_fill_gradient(low = "blue",high = "red") +
guides(color = "none", fill = "none", alpha = "none")
})
I'm wondering if it's possible to hook into the code in an external R script that is read by knitr.
Specifically, say that you have the following R file
test.R
## ---- CarPlot
library(ggplot2)
CarPlot <- ggplot() +
stat_summary(data = mtcars,
aes(x = factor(gear),
y = mpg
),
fun.y = "mean",
geom = "bar"
)
CarPlot
Imagine that you wanted to use this graph in multiple reports, but in one of these reports you want the graph to have a title and in the other report you do not.
Ideally, I would like to be able to use the same external R script to be able to do this so that I do not have to make changes to multiple R files in case I decide to change something about the graph.
I thought that one way to perhaps do this would be by setting the fig.show chunk option to hold—since it will "hold all plots and output them in the very end of a code chunk"—and then appending a title to the plot like so:
test.Rnw
\documentclass{article}
\begin{document}
<<external-code, cache=FALSE,echo=FALSE>>=
read_chunk('./test.R')
#
<<CarPlot,echo=FALSE,fig.show='hold'>>=
CarPlot <- CarPlot + ggtitle("Plot about cars")
#
\end{document}
This, however, does not work. Although the plot is printed, the title that I tried to append does not show up.
Is there some way to do what I would like to do?
You don't want to show the plot created by test.R, so you should set fig.show = 'hide' or include = FALSE for that chunk:
<<external-code, cache=FALSE,echo=FALSE,fig.show = 'hide'>>=
read_chunk('./test.R')
#
You do want to show the plot after modification, so you have to print it:
<<CarPlot,echo=FALSE>>=
CarPlot <- CarPlot + ggtitle("Plot about cars")
CarPlot
#
fig.show = 'hold' is used if you have a large code chunk that prints a plot in the middle, but you don't want the plot to show in your document until the end. It doesn't apply to this case.
I would like to find a way to use the LaTeX \ref{} markup to comment in the R code within a Sweave .Rnw file. Here are two examples, one in print
http://cm.bell-labs.com/cm/ms/departments/sia/project/nlme/UGuide.pdf
and one to use to work with:
The .Rnw file
% File: example.Rnw
\documentclass{article}
\usepackage{fullpage}
\usepackage{graphics}
\usepackage{Sweave}
\usepackage[margin = 10pt, font=small, labelfont={bf}]{caption}
\begin{document}
Here is an example file to show what I want to do. I would like to figure out how to use the \LaTeX\ reference command to reference a figure being generated by R code. Note in the R code, in a comment there is a reference to the figure, but of course the output file shows a verbatim copy of the \LaTeX\ markup. Does anyone know how to get something for Figure \ref{fig2}?
<< example plot >>=
library(reshape)
library(ggplot2)
n <- 100
lambda <- 1 / 3
x <- seq(0, qexp(0.999, rate = lambda), length = n)
q1.a <- data.frame(x = x,
f = dexp(x, rate = lambda),
F = pexp(x, rate = lambda))
q1.a <- melt(q1.a, id.vars = 'x')
g <- ggplot(q1.a) + # Produces \ref{fig1}
aes(x = x, y = value) +
geom_line() +
facet_wrap( ~ variable, scale = "free_y")
ggsave(g, filename = "example1.jpeg")
#
\begin{figure}[h]
\centering
\includegraphics[width = 0.48\textwidth]{./example1}
\caption{Exponential Distribution based plots.}
\label{fig1}
\end{figure}
Here is more of what I would like to see:
<< example plot 2 >>=
ggsave(g + geom_point(), filename = "example2.jpeg") # Produces Figure 2
#
\begin{figure}
\centering
\includegraphics[width = 0.48\textwidth]{./example2}
\caption{Exponential Distribution based plots with points and lines.}
\label{fig2}
\end{figure}
\end{document}
and the pdf is build with the R commands
Sweave(file = 'example.Rnw',
engine = "R",
keep.source = 'TRUE',
echo = 'TRUE',
results = 'verbatim')
tools::texi2dvi(file = "example.tex",
pdf = TRUE,
clean = TRUE)
Any insight on how do this would be great.
Here is one way to solve this issue by redefining the Sinput environment in which source code is wrapped by Sweave. By default, it is a simple verbatim environment which is not processed by latex for tokens. The trick is to redefine it to use the alltt environment which allows some tokens to be parsed inside the alltt environment. Note that this might lead to unwanted side effects that I am not aware of, so use with caution!
Here is a reproducible example that works. If you compile it, you will generate a file where ref{fig1} is replaced by the figure number.
\documentclass{article}
\usepackage{Sweave}
\usepackage{alltt}
\renewenvironment{Sinput}{\begin{alltt}}{\end{alltt}}
\begin{document}
In this document, we will create a plot using `R`, and reference its position in
the source code.
<<produce-plot, results = hide>>=
pdf('example1.pdf')
plot(1:10, 1:10) # Produces Figure \ref{fig1}
dev.off()
#
\begin{figure}
\includegraphics{example1.pdf}
\caption{Figure 1}
\label{fig1}
\end{figure}
\end{document}