I have a .Rnw file that I am able to compile into a PDF using the "Compile PDF" button in RStudio (or Command+Shift+k). However, when I use knit2pdf the graphics are not created and the complete PDF is not created. Why would this happen? How do you specifically set where the images will be stored so that pdflatex can find them?
Here is an example. I am aware that this question that I posted a few days ago has a similar example, but in my mind these are two different questions.
This file will run just fine and produce a PDF if I hit "Compile". I don't get any errors, the figure is produced in the /figure directory, and all is well.
%test.Rnw
\documentclass{article}
\usepackage[margin=.5in, landscape]{geometry}
\begin{document}
This is some test text!
<<setup, include=FALSE, results='hide', cache=FALSE>>=
opts_chunk$set(echo=FALSE, warning = FALSE, message = FALSE,
cache = FALSE, error = FALSE)
library(ggplot2)
#
<<printplotscreen, results='asis'>>=
ggplot(diamonds) +
geom_bar(aes(x = color, stat = "bin"))
#
\end{document}
However, when I run this script that is intended to do exactly the same thing as hitting "Compile" (is it?) the figure is not created and I get the not-surprising error below about not being able to find it.
#test.R
library("knitr")
knit2pdf(input = "~/Desktop/thing/test.Rnw",
output=paste0('~/Desktop/thing/test','.tex'))
Error in texi2dvi(file = file, pdf = TRUE, clean = clean, quiet = quiet, :
Running 'texi2dvi' on 'test.tex' failed.
LaTeX errors:
! LaTeX Error: File `figure/printplotscreen-1' not found.
NOTE: If you are trying to reproduce this (and thanks!) then make sure you run the knit2pdf script FIRST to see that it doesn't create the figures. If you hit "Compile" first then the figures will be there for knit2pdf to use, but it will not accurately represent the situation.
The solution: Make sure to set the working directory to the project directory before using knit2pdf, then shorten the "input" path to just the .Rnw file. Thus...
test.R
library("knitr")
diamonds = diamonds[diamonds$cut != "Very Good",]
setwd("/Users/me/Desktop/thing")
knit2pdf(input = "test.Rnw", output = "test.tex")
Here are some references on this issue:
Changing working directory will impact the location of output #38
;
make sure the output dir is correct (#38)
It seems that when using knit2pdf(), it automatically set your output files to the directory where your input file in. And the author doesn't recommend us changing work-directory during the middle of a project.
So the current solution for me is to save the working directory as old one(getwd()), change the working directory to where you want to save the output files, use knit2pdf() to output files, and change the working directory to the original one finally.
Related
I saw someone ask a similar question to this but did not have a conclusive answer... I am trying to knit an rmd file to html and am using a function that I wrote in a .R file. I get an error saying the function can not be found etc.
Also just a note that when I run the chunk of code that the function is called for, it works. Just an error when knitting.
This is because you're using the knit button in Rstudio which creates a new session then executes rmarkdown::render, in order to use locally defined function you have to call rmarkdown::render from the console.
Note: that this will block the console until the .Rmd file is rendered.
my.envir <- new.env(parent=baseenv())
local({
f <- function() { ... }
#...
}, my.envir)
# OR source your file directly into my.envir
source("ur.file.R", local = my.envir)
rmarkdown::render(input, # path to the .Rmd file
output_format = "html_document", # output type if not set it'll use the first one found in the yaml header
output_file = NULL, # name of the output file by default it will be the
# name of the .Rmd with the extension changed
clean = TRUE, # set to FALSE if you want to keep intermediary files
envir = my.envir, # this where the magic happens
# if you don't want to modify the global env you can create your own environment and add the function to it
quiet = FALSE # set to TRUE if you want to suppress the output
)
EDIT following #KonardRudolph's comments:
It's better to source your file into the rmd itself, as the main goal of Rmarkdown is reproducible research.
```{r setup, include=FALSE}
.
.
.
source("path/to/file.R")
```
I'm trying to run markdown (with parameters) in a for loop. If i don't specify the output directory it works just fine, but if I specify a different directory from the working directory I get an error on compiling.
My code is similar to this:
n_report<-c(1,2,3,5)
for (n in n_report){
rmarkdown::render(input = "C:/Users/.../report.Rmd",
output_dir = "//192.168.5.4/.../.../.../REPORT", #removing this line the code works
output_format = "pdf_document",
output_file = paste0("ST", n, ".pdf"),
params = list(n=n)
}
The output pdf must be saved on an internal server, I think that the problem depends on a wrong interpretation of the firs two "//", on console I get this error:
Error: Failed to compile \\192.168.5.4/.../.../.../REPORT/ST1.tex. See https://yihui.name/tinytex/r/#debugging for debugging tips.
With everything else markdown::render the path works perfectly.
The "report.Rmd" generate an output in pdf with kableExtra package.
Can someone help me?
Problem
I want to knit multiple PDFs from a single data frame. Therefore I've tried various solutions, but my knowledge in R, R Studio, LaTex, knitr is very limited so I wasn't able to adapt some solution approaches and finally tried it on my own. I actually think my code is absolutely not the way you actually use to achieve what I want to achieve. So, please feel free to tell me where and what I can/should improve.
I would be really grateful for some help. I've been googling for hours now and I would also appreciate if you could recommend me any tutorial/guide/explanation. I don't even know where to start.
Current State: Solved
Code
main.R
for(i in 1:nrow(mtcars)) {
g_title <- rownames(mtcars)[i]
knit2pdf(input = "main.Rnw",
output = paste0("output\\", g_title, ".pdf"),
quiet = FALSE,
envir = parent.frame())
}
template.Rnw
\documentclass{article}
\usepackage[ngerman]{babel}
\begin{document}
\begin{titlepage}
Titlepage
\end{titlepage}
\tableofcontents
\newpage
\section{Topic 1}
\newpage
\section{Topic 2}
\end{document}
Solution Approaches
Global Variables
I tried to create global variables which are altered by a for loop. These variables are then used in the .Rnw file in form of a function. I wasn't able to get this working due unknown errors.
Code in the .R file:
printPlot <- function() {
print(g_plot)
}
for(i in 1:nrow(mtcars)) {
g_title <- rownames(mtcars)[i]
g_plot <- ggplot(mtcars[i,], aes(x = cyl, y = disp) ) +
geom_point()
knit2pdf(input = "main.Rnw",
output = paste0("output\\", g_title, ".pdf"),
quiet = FALSE,
envir = parent.frame())
}
Code in the .Rnw file:
<<>>=
printPlot()
#
Errors:
The PDFs are created, but their contents are messed up. You can see it in the image under 'Current State'.
I also receive several error/warning messages, e.g.:
Warning messages:
1: running command '"C:\Users\Marc\AppData\Local\Programs\MIKTEX~1.9\miktex\bin\x64\texify.exe"
--quiet --pdf "Mazda RX4.pdf" --max-iterations=20 -I "C:/PROGRA~1/R/R-33~1.2/share/texmf/tex/latex" -I
"C:/PROGRA~1/R/R-33~1.2/share/texmf/bibtex/bst"' had status 1
2: running command '"C:\Users\Marc\AppData\Local\Programs\MIKTEX~1.9\miktex\bin\x64\texify.exe"
--quiet --pdf "Mazda RX4 Wag.pdf" --max-iterations=20 -I "C:/PROGRA~1/R/R-33~1.2/share/texmf/tex/latex" -I
"C:/PROGRA~1/R/R-33~1.2/share/texmf/bibtex/bst"' had status 1
MakeFile
I just read the first time about makefile. Maybe this could help solving the problem.
If I got it right makefile is used with Markdown and not directly with LaTex. This seems to be a massive loss in performance. This point is quite important to me, so I will try to find another solution.
Other SO Questions
In most of the cases I tried to adapt the code, but simply failed, because I am missing knowledge to understand the given solution approaches.
R Knitr PDF: Is there a posssibility to automatically save PDF reports (generated from .Rmd) through a loop?
Using loops with knitr to produce multiple pdf reports… need a little help to get me over the hump
Can Sweave produce many pdfs automatically?
From the question, I'm not entirely sure about the expected output, but there concept is clear. And although the task itself is quite simple, surprisingly many things can go wrong.
Code:
code.R
library(knitr)
library(ggplot2)
dir.create(path = "output/")
opts_knit$set(base.dir = "output/")
for(i in 1:nrow(mtcars)) {
filename <- rownames(mtcars)[i]
knit(input = "template.Rnw", output = paste0("output/", filename, ".tex"))
tools::texi2pdf(paste0("output/", filename, ".tex"), clean = TRUE)
file.copy(from = paste0(filename, ".pdf"), to = paste0("output/", filename, ".pdf"))
# file.remove(paste0(filename, ".pdf")) # this will DELETE filename.pdf from the current working directory (should be safe because we just created this file)
}
template.Rnw
\documentclass{article}
\begin{document}
<<>>=
ggplot(mtcars[i,], aes(x = cyl, y = disp) ) + geom_point()
#
\end{document}
We need to set base.dir because the current working directory is one level above the directory where the document is created. This would lead to wrong figure paths: knitr produces the plots in figure/ but they should be in output/figure/. Consequently, compilation will fail.
For some reason knit2pdf cannot compile the generated intermediate TEX file. Therefore I use knit to produce a TEX file and then tools::texi2pdf to compile this file to PDF.
Note how variables from code.R are visible to the code in the template document. That's why i can be used in template.Rnw.
With the Rmd files on root (eg. on my /knitr-jekyll/) they are turning into md files, but not on html files. Thus, they appear as simple markdown text.
I tried to put them on /_source and on /_posts but it get's worse, in this case I also don't get the md files.
I found creating a separate folder all together solves the problem.
/kintr-jekyll/_rmd/test.Rmd
But do remember that when you knit your Rmd to md that you knit to the _post folder if you using the standard bootstrap template. Also make sure that you specified your figure output. Easiest is to write some function which does this for you:
KnitPost <- function(input, base.url = "/") {
require(knitr)
opts_knit$set(base.url = base.url)
fig.path <- paste0("figures/", sub(".Rmd$", "", basename(input)), "/")
opts_chunk$set(fig.path = fig.path)
opts_chunk$set(fig.cap = "center")
render_jekyll()
knit(input, envir = parent.frame())
Lastly, go make sure in your .md file in knitr-jekyll/_post that the figures are clearly referenced. This should be within your test.md:
<img align="middle" src="/figures/test/test_image.jpg">
This link might help: R-Bloggers post about jekyll
I try to do a blog using the trio jekyll, rmarkdown and github (as here: http://yihui.name/knitr-jekyll/)
I have all my .Rmd in _source, and I have this issue that sometimes the plots are knit in base 64 images and sometimes saved in a figure folder.
First question, why?
Second question: when my plot are saved as images, the path in the html appear to be figure/source/. Knowing that the destination folder is /blog/ (my baseurl in _config.yml), to make it work, it should be blog/figure/source.
Strangely, they are displayed locally and when I open the html with my browser.
But when I deploy my website on github, the images aren't displayed, as the path is incorrect.
How to define the path to /blog/figure instead of /figure/ ?
Edit: the link to my blog, still in development:
http://yvescr.github.io/
But the Rmd don't appear in the github account, as the folder I synchronised with github is the destination file of the jekyll generation.
_config.yml:
# Build settings
markdown: kramdown
baseurl: "/blog"
In R:
jekyll(dir = ".", input = "_source", output = "_posts", script = c("Makefile", "build.R")
, command = "jekyll build --destination ../blog")
build.r:
local({
# fall back on '/' if baseurl is not specified
baseurl = servr:::jekyll_config('.', 'baseurl', '/')
knitr::opts_knit$set(base.url = baseurl)
# fall back on 'kramdown' if markdown engine is not specified
markdown = servr:::jekyll_config('.', 'markdown', 'kramdown')
# see if we need to use the Jekyll render in knitr
if (markdown == 'kramdown') {
knitr::render_jekyll()
} else knitr::render_markdown()
# input/output filenames are passed as two additional arguments to Rscript
a = commandArgs(TRUE)
d = gsub('^_|[.][a-zA-Z]+$', '', a[1])
knitr::opts_chunk$set(
fig.path = sprintf('blog/figure/%s/', d),
cache.path = sprintf('cache/%s/', d)
)
knitr::opts_knit$set(width = 70)
knitr::knit(a[1], a[2], quiet = TRUE, encoding = 'UTF-8', envir = .GlobalEnv)
})
makefile:
all:
Rscript -e "servr::jekyll('..')"
clean:
rm -r ../blog/
I solve my issue, I post it here in case people have the same:
The jekyll() function in R compile the .rmd (in _source) in .md(in _post) with knitr(I think) then call the jekyll command.
Here, my issue was that when I changed the _config.yml file, with modification of the path, the .md are not re-created and so the path is not changed.
To make it work, I had to delete manually the .md in _source then re-run the jekyll() function.
Concerning the images, they are compiled as 64 images when I use rmarkdown without cache.
With the cache, knitr create images in a folder.