Is there a way to print, from within R, a LaTeX table directly to an image file (for inclusion in another document/webpage). Basically, I'd like to supply LaTeX code to a function that saves it as an image to the working directory.
Pipe dreams?
There are various LaTeX-to-Image converter scripts, designed to do things like convert equations into images for including on web pages.
If you can find one of those (dvipng perhaps?) then you can go from a table in R to LaTeX easy enough and then from LaTeX to png.
If you have dvipng, you can leverage Hmisc's latex conversions to make a neater function to do it:
dvipng.dvi <-
function (object, file, ...)
{
cmd <- if (missing(file))
paste("dvipng -T tight", shQuote(object$file))
else paste("dvipng -T tight", "-o", file, shQuote(object$file))
invisible(sys(cmd))
}
And then you can do:
> tt # here is a table
y
x 1 2 3
1 9 12 11
2 18 9 10
3 10 7 14
> dvipng.dvi(dvi.latex(latex(tt)))
And that will produce a png file with a random name in the working directory. The -T tight option will crop all the whitespace from round it.
That's about as direct as I can think it possible.
Linux or Windows or Mac or Atari?
xtable provides the option to output either latex or html markup. You could put the html in directly.
Having said that I too would like to be able to go directly from knit or sweave to png or svg. I was trying to do this just last week. I am building an inkscape infographic (svg) and have been looking for a way to insert a linked image of a table that updates by running R code.
In initial testing I combined the use of xtable and Spacedman's (+1) code to get some nice png output (Ubuntu). -D option allows controlling of resolution.
I'm looking into a dvi->svg converter which is more like what I am after.
http://dvisvg.sourceforge.net/
dvipng.dvi <- function (object, file, res=600)
{
if (missing(file)){
invisible(sys(
paste("dvipng -T tight", "-D", res, shQuote(object$file)))
)
}
else{
invisible(sys(
paste("dvipng -T tight", "-D", res, "-o", file, shQuote(object$file)))
)
}
}
tt <- head(iris)
dvipng.dvi(dvi.latex(latex(xtable(tt))), file='iris.png')
With Spaceman's answer, I was able to come up with a solution that does not rely on latex from the Hmisc package as latex was causing some path problems for me:
table.png <- function(obj, name) {
first <- name
name <- paste(name,".tex",sep="")
sink(file=name)
cat('
\\documentclass{report}
\\usepackage[paperwidth=5.5in,paperheight=7in,noheadfoot,margin=0in]{geometry}
\\begin{document}\\pagestyle{empty}
')
print(xtable(obj))
cat('
\\end{document}
')
sink()
texi2dvi(file=name)
cmd <- paste("dvipng -T tight", shQuote(paste(first,".dvi",sep="")))
invisible(sys(cmd))
cleaner <- c(".tex",".aux",".log",".dvi")
invisible(file.remove(paste(first,cleaner,sep="")))
}
The kableExtra package allows to make nice and customized tables via LaTeX or HTML. It also has a function to export such standalone tables to, for example, PNG or PDF via webshot. Here is an example:
library(kableExtra)
knitr::kable(mtcars[1:6, 1:5], "latex", booktabs = TRUE, linesep = "") %>%
kable_styling(full_width = TRUE, font_size = 12) %>%
column_spec(1, width = "4cm") %>%
save_kable(file = "table.png")
I don't have a good answer that includes using R, but if you were desperate, I suppose a 'print screen' and a copy to Paint or other such program and finally saving it would at least get you the image in a storable format.
I've created 'step by step' user documentation this way when other options weren't available.
Related
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.
I would want to export all the content of r script into pdf. Could it be possible?
I used these commands export, but what I see I just exported graphics
pdf(file = "example.pdf")
dev.off()
Thank you!
setwd("C:/Users/Prat/Desktop/c")
> dir()
[1] "script.R"
> knitr::stitch('script.r')
output file: script.tex
In my folder doesn't appears a script.pdf else a script.tex and a folder with the pictures in pdf
You can do this with the knitr package. Here's a workflow:
Save your script as a file (e.g., myscript.r)
Then run knitr::stitch('myscript.r')
The resulting PDF will be saved locally as myscript.pdf. You can use browseURL('myscript.pdf') to view it.
You can generate html file by using,
knitr::stitch_rhtml('filename.r')
As .tex file is not easily readable but html files can view in any browser easily.
For everyone who is looking for an easy and fast solution, I would propose using the function capture.output (https://www.rdocumentation.org/packages/utils/versions/3.6.2/topics/capture.output) from utils.
One only needs to 1.) capture what ever command one wants to run and assign it to a variable and 2.) then print that variable. Images can be printed along the way as you can see. The example on the webpage I linked above does not use markdown.
Here my example with markdown (this is really all one needs):
```{r, echo = F}
# fake data-set
x = rnorm(50, mean = 3.3, sd=1)
y = rnorm(50, mean = 3.1, sd=0.9)
z = rnorm(50, mean = 3.2, sd=1.1)
# create dataframe
df <- data.frame(x, y, z)
# adding a graphic
plot(df$x, df$y)
# create a model as example
linearMod <- lm(y ~ x + z, data=df)
# all one needs to capture the output!!:
bla <- capture.output(summary(linearMod))
print(bla)
```
Remark: if one also wants to print the command, that is also easy. Just replace "echo = F" with "warning = F" or remove the text altogether if you also wanna have the warnings printed, in case there are any.
I was having the same issue, but I realized I was working in R 4.1 and ignored the warning that knitr was created using R 4.2. However after updating my R version, I was also just getting a .tex file but when I read the .log file I found the error "sh: pdflatex: command not found."
I used this suggestion with success:
Have you installed a LaTeX distribution in your system? For rmarkdown,
tinytex is recommended, you would need to install the R package and
then the TinyTex distribution.
install.packages('tinytex')
tinytex::install_tinytex()
Make sure you not only install the package but also run that second command tinytex::install_tinytex() as I made that mistake also before finally getting the program to create a pdf file.
Here is the link to the site where I found this method.
https://community.rstudio.com/t/knitting-error-pdflatex-command-not-found/139965/3
Please use the below set of codes (you need to modify it according to your dataset/data-frame name).
library(gridExtra)
library(datasets)
setwd("D:\\Downloads\\R Work\\")
data("mtcars") # Write your dataframe name that you want to print in pdf
pdf("data_in_pdf.pdf", height = 11, width = 8.5)
grid.table(mtcars)
dev.off()
Thanks.
I have a folder with multiple JPEG files. How do I generate a PDF file from these JPEGs in R?
One JPEG = 1 PDF page. Images are of the same size.
Thanks a lot in advance.
You can do this easily using Latex. Which is nice, because then you can just use Sweave to do the whole thing.
You can do something along the lines of :
% This is some Sweave file
\documentclass{article}
\usepackage{graphicx}
\begin{document}
<<results=tex,echo=FALSE>>=
mypics <- dir('mypics')
for(i in mypics){
cat("\\includegraphics{", i, "}\n\n", sep = "")
}
#
\end{document}
OK, you'll have to set up your Sweave pipeline, but with a bit of tweaking you can automate the whole process easily.
if you insist on using R (other tools are more suitable), try something like this (slow, untested):
lf = list.files(pattern = "jpeg") # image filenames
library(jpeg)
jpegs = lapply(lf, readJPG)
library(grid)
pdf("output.pdf", width=8, height=4)
grid.raster(jpegs[[1]])
lapply(jpegs[-1], function(x) {grid.newpage() ; grid.raster(x)} ) -> bquiet
dev.off()
If you insist on using R to do this then you can open a pdf plotting device, par to set the margins (default will probably be to big and not centering), then in a loop use plot.new to start a new page and plot.window to set up the coordinates, etc. without plotting axes etc., use the read.jpeg function from the ReadImages package (or other tool/package to read, EBImage is another possibility) then rasterImage to plot the jpeg to the pdf device (or replace some of those steps with other image plotting functions, such as the plot method in ReadImages).
But overall it is probably easier/quicker/better/... to use a tool better designed for this type of thing. The ImageMagick suite of programs comes to mind, LaTeX has also been mentioned, and there are probably other tools as well.
I found this great tutorial on how to modify the css formatting of a HTML report created with markdown and knitr in Rstudio. The post can be found here.
I was hoping to build on this concept and mimic the layout of the page here by using the same css. I tried to simply copy/paste/combine the two css files I found when I viewed the page's source.
Any help you can lend would be greatly appreciated! This is my first attempt and doing anything CSS.
This is the method provided by RStudio: http://www.rstudio.com/ide/docs/authoring/markdown_custom_rendering
options(rstudio.markdownToHTML =
function(inputFile, outputFile) {
require(markdown)
markdownToHTML(inputFile, outputFile, stylesheet='custom.css')
}
)
I've never been able to get that working properly so I do it a little differently:
I do this by creating the standard output file, then dropping the header and css code at the top in R:
tmp <- readLines("your.html")
tmp <- tmp[-c(1:50)] # or however many lines it is before the css ends
write(tmp,"your.html")
Then I use pandoc to add my own css in a standalone file
system("pandoc -s -S your.html -c your.css -o output.html")
Outside of RStudio (may work in it too - I'm not sure as I don't use it much), you can use option 'markdown.HTML.stylesheet' to set a custom style sheet. It will then import everything from your .css file into the newly created html file.
Here is an example:
## Set file names
htmlName <- "test.html"
rmdName <- gsub("html","Rmd", htmlName)
stylesheetName <- 'style.css'
## Generate rmd file from R
sink(file = rmdName, type='output')
cat('\n<textarea maxlength="3000" cols="70">')
cat("Hello World!")
cat('</textarea>\n')
sink()
## Generate style sheet from R
sink(file = stylesheetName, type='output')
cat("textarea {color: #a10000; }\n")
sink()
## Set knitr options and knit html
require(knitr)
options(markdown.HTML.stylesheet = stylesheetName)
knit2html(rmdName, output = htmlName)
I'm using knitr for my analysis. I can save graphs in PDF format with \SweaveOpts{dev=pdf} and in PNG format with \SweaveOpts{dev=png}. I'm interested to save graphs both in PDF and PNG format in one run but to use the PDF in the final documents interactively.
How can I do this?
Here comes the real solution:
Knitr 0.3.9 starts to support multiple devices per chunk (for now, you have to install from GitHub); in your case, you can set the chunk option dev=c('pdf', 'png') to get both PDF and PNG files.
Here is a solution that uses ImageMagick to convert PDF files to PNG. Of course you have to install ImageMagick first, and make sure its bin directory is in PATH:
knit_hooks$set(convert = function(before, options, envir) {
# quit if before a chunk or no figures in this chunk
if (before || (n <- options$fig.num) == 0L) return()
# only convert pdf files
if (options$fig.ext != 'pdf') return()
# use ImageMagick to convert all pdf to png
name = fig_path() # figure filename
owd = setwd(dirname(name)); on.exit(setwd(owd))
files = paste(basename(name), if (n == 1L) '' else seq(n), sep = '')
lapply(files, function(f) {
system(sprintf('convert %s.pdf %s.png', f, f))
})
NULL
})
Basically this hook is executed after a chunk and run convert foo.pdf foo.png on all PDF figures. You can use it like
<<test-png, convert=TRUE>>=
plot(1); plot(2)
#
Or if you put all figures in a separate directory, you can run convert directly in that directory (i.e. do not have to call system() in R).
This is not an ideal solution but should work. To make use of R's native png() device, you need to answer my question in the above comment first.