I try to create multiple plotly figures in a Rmarkdown document using loop or lapply.
The R script:
require(plotly)
data(iris)
b <- lapply(setdiff(names(iris), c("Sepal.Length","Species")),
function(x) {
plot_ly(iris,
x = iris[["Sepal.Length"]],
y = iris[[x]],
mode = "markers")
})
print(b)
works well, but it fails when included in a knitr chunk:
---
output: html_document
---
```{r,results='asis'}
require(plotly)
data(iris)
b <- lapply(setdiff(names(iris), c("Sepal.Length","Species")),
function(x) {
plot_ly(iris,
x = iris[["Sepal.Length"]],
y = iris[[x]],
mode = "markers")
})
print(b)
```
I tried replacing print(b) with a combination of lapply eval and parse but only the last figure was displayed.
I suspect a scoping/environment issue but I cannot find any solution.
Instead of print(b), put b in htmltools::tagList(), e.g.
```{r}
library(plotly)
b <- lapply(
setdiff(names(iris),
c("Sepal.Length","Species")),
function(x) {
plot_ly(iris,
x = iris[["Sepal.Length"]],
y = iris[[x]],
mode = "markers")
}
)
htmltools::tagList(b)
```
Note: Before Plotly v4 it was necessary to convert the Plotly objects to htmlwidgets using Plotly's as.widget() function. As of Plotly v4 they are htmlwiget objects by default.
For people who are interested in the technical background, you may see this blog post of mine. In short, only top-level expressions get printed.
I found a "dirty" solution by using temp file and kniting it :
```{r,echo=FALSE}
mytempfile<-tempfile()
write("```{r graphlist,echo=FALSE}\n",file=mytempfile)
write(paste("p[[",1:length(p),"]]"),file=mytempfile,append = TRUE)
write("\n```",file=mytempfile,append = TRUE)
```
`r knit_child(mytempfile, quiet=T)`
But it's unsatisfactory.
For anyone struggling with a loop, here's what worked for me.
p=list()
for (n in 1:3){
p[[n]] <- plot_ly(x = 1:100, y = rnorm(100)+n, mode = 'lines', type="scatter")
}
htmltools::tagList(p)
I.e. it doesn't matter if the list p is created in a loop or lapply, etc. as long as you call htmltools::tagList outside the loop.
Thanks to Yihui for helping me get there and for immense work developing and helping with these tools.
Related
I'm testing the Officedown-package, but encounter some issues. From the two examples below, the first one produces a word-file, but with warning. The second one stops due to an error I don't understand.
Example 1
---
title: "Style text with officedown"
output:
officedown::rdocx_document: default
---
```{r}
library(officedown)
library(officer)
library(ggplot2)
library(flextable)
ft <- fp_text(color = 'red', bold = TRUE)
```
# Test
The **officedown** package is
`r ftext('awesome', ft)`!
```{r}
df <- data.frame(A = 1:3,
B = 1:3)
mytable <- flextable(df, theme_fun = theme_box)
mytable
```
Warning 1
Example 2
Just one chunk is added to the previous example. Here I make and print a ggplot, but the same error occurs if the chunk only contains df (print the dataframe)
```{r plot, fig.cap="a cap"}
p <- ggplot(df, aes(A,B))+geom_point()+theme_bw()
print(p)
```
Rather silly to find the solution minutes after you turn to stackoverflow because google doesn't provide the solution:
I installed the cachem-package. I assume it should have come with the officedown-installation, but apparently it didn't.
I'm writing in rmarkdown to produce a html_document, I want to write a latex equation in the axis titles.
Is there a way?
x <- c(0,1,1,1,2,2,2,3)
Fn <- ecdf(x)
plot(Fn , lwd = 2, main="",ylab = "$F(x)$",xlab="$x$",yaxt="n")
As #MrFlick pointed out, there is a certain syntax for mathematical annotations. Sometimes it might not be enough due to complex formulas or certain symbols.
A way around this that avoids rendering a pdf plot (created using tikz) inside a pdf viewer inside the HTML document is converting it to another format.
Here I change the plot hook to convert the tikz pdf plot to png and include it using the original plot hook.
---
title: "Test"
output: html_document
---
```{r, include=F}
library(pdftools)
library(png)
library(knitr)
oldHook <- knit_hooks$get("plot")
knit_hooks$set(plot = function(x, options) {
fname <- gsub("pdf", "png", x)
bitmap <- pdf_render_page(x, page = 1, dpi = 300)
png::writePNG(bitmap, fname)
oldHook(fname, options)
})
```
```{r, dev='tikz'}
x <- c(0,1,1,1,2,2,2,3)
Fn <- ecdf(x)
plot(Fn , lwd = 2, main="",ylab = "$F(x)$",xlab="$x$",yaxt="n")
```
You can use latex2exp
library(latex2exp)
plot(Fn , lwd = 2, main="",
ylab = latex2exp("$F(x)$"),
xlab=latex2exp("$x$"),yaxt="n")
Or in R Base
plot(Fn , lwd = 2, main="",
ylab = expression("F(x)"),
xlab=expression("x"),
yaxt="n")
Edit: Sorry, the answer below is for PDF output. It's probably possible to do something similar for HTML output by processing the tikz figure into a PNG or SVG file and including that, but I haven't worked out the details.
You could try the tikzDevice package. This example is based on Yihui's suggestion here: https://github.com/daqana/tikzDevice/issues/60.
---
output:
pdf_document
header-includes:
- \usepackage{tikz}
---
```{r setup}
library(knitr)
knit_hooks$set(plot = function(x, options) {
if ('tikz' %in% options$dev && !options$external) {
hook_plot_tex(x, options)
} else hook_plot_md(x, options)
})
```
Text.
```{r test, dev='tikz', external=FALSE}
x <- c(0,1,1,1,2,2,2,3)
Fn <- ecdf(x)
plot(Fn , lwd = 2, main="",ylab = "$F(x)$",xlab="$x$",yaxt="n")
```
Here's the output:
I have created a Rmarkdown document with shiny runtime. The reason is that depending on some selections, the data is fetched from a database and the output (tables and plots) are updated accordingly to the new selections. For the plots I was using ggplot2 and this is working fine, but I wanted to introduce more interaction using rCharts, and here is where I'm stuck, having tried a variety of combinations using renderPlot(), renderChart() and renderChart2() returning the rCharts object p, using p$show() or p$print() with different parameters, none of the options working for me.
These are code samples I'm using.
Header:
---
title: "my title"
runtime: shiny
output:
html_document
ext_widgets: {rCharts: [libraries/nvd3]}
---
Here is the plotting code
```{r, echo=FALSE, comment = NA, results = "asis", comment = NA, tidy = F}
renderPlot({
data.dt <- data.table(analysisData())
aggdata2 <- as.data.frame(data.dt[, lapply(.SD, sum), by = date])
aggdata2 <- aggdata2[with(aggdata2,order(date)),]
p <- nPlot(y ~ date, data = aggdata2, type = "lineChart", width = 600)
p$xAxis(
tickFormat = "#!
function(d) {return d3.time.format('%Y-%m-%d')(new Date(d*1000*3600*24));}
!#"
)
#p$print()
#p$show('iframesrc', cdn =TRUE, include_assets=TRUE)
return(p)
})
```
Which is indeed the best solution I have found so far: it is opening a new window with the chart that I want to create. However, it leaves a blank space in the markdown html where I want the chart to be.
For the analysisData() function here is a simplified code
```{r, echo=FALSE}
analysisData <- reactive({
variable1 = input$variable1
variable2 = input$variable2
tables = "sqlTable"
drv <- dbDriver("PostgreSQL")
dbname <- "dbname"; dbuser <- "dbuser";
dbport = dbport
dbhost <- "dbhost.com";
con <- dbConnect(drv, host=dbhost, port = dbport, dbname=dbname, user=dbuser)
selectStatement = "select * from %s where variable1=%s and variable2=%s"
query = sprintf(selectStatement, tables, variable1, variable2)
dataset <- dbGetQuery(con,query)
lapply(dbListConnections(drv),dbDisconnect)
dbUnloadDriver(drv)
dataset$date <- as.Date(dataset$date)
dataset
})
```
Do you have any suggestions on how can I solve the problem? Any hint is appreciated.
I would like to create an automated knitr report that will produce histograms for each numeric field within my dataframe. My goal is to do this without having to specify the actual fields (this dataset contains over 70 and I would also like to reuse the script).
I've tried a few different approaches:
saving the plot to an object, p, and then calling p after the loop
This only plots the final plot
Creating an array of plots, PLOTS <- NULL, and appending the plots within the loop PLOTS <- append(PLOTS, p)
Accessing these plots out of the loop did not work at all
Even tried saving each to a .png file but would rather not have to deal with the overhead of saving and then re-accessing each file
I'm afraid the intricacies of the plot devices are escaping me.
Question
How can I make the following chunk output each plot within the loop to the report? Currently, the best I can achieve is output of the final plot produced by saving it to an object and calling that object outside of the loop.
R markdown chunk using knitr in RStudio:
```{r plotNumeric, echo=TRUE, fig.height=3}
suppressPackageStartupMessages(library(ggplot2))
FIELDS <- names(df)[sapply(df, class)=="numeric"]
for (field in FIELDS){
qplot(df[,field], main=field)
}
```
From this point, I hope to customize the plots further.
Wrap the qplot in print.
knitr will do that for you if the qplot is outside a loop, but (at least the version I have installed) doesn't detect this inside the loop (which is consistent with the behaviour of the R command line).
Wish to add a quick note:
Somehow I googled the same question and get into this page.
Now in 2018, just use print() in the loop.
for (i in 1:n){
...
f <- ggplot(.......)
print(f)
}
I am using child Rmd files in markdown, also works in sweave.
in Rmd use following snippet:
```{r run-numeric-md, include=FALSE}
out = NULL
for (i in c(1:num_vars)) {
out = c(out, knit_child('da-numeric.Rmd'))
}
```
da-numeric.Rmd looks like:
Variabele `r num_var_names[i]`
------------------------------------
Missing : `r sum(is.na(data[[num_var_names[i]]]))`
Minimum value : `r min(na.omit(data[[num_var_names[i]]]))`
Percentile 1 : `r quantile(na.omit(data[[num_var_names[i]]]),probs = seq(0, 1, 0.01))[2]`
Percentile 99 : `r quantile(na.omit(data[[num_var_names[i]]]),probs = seq(0, 1, 0.01))[100]`
Maximum value : `r max(na.omit(data[[num_var_names[i]]]))`
```{r results='asis', comment="" }
warn_extreme_values=3
d1 = quantile(na.omit(data[[num_var_names[i]]]),probs = seq(0, 1, 0.01))[2] > warn_extreme_values*quantile(na.omit(data[[num_var_names[i]]]),probs = seq(0, 1, 0.01))[1]
d99 = quantile(na.omit(data[[num_var_names[i]]]),probs = seq(0, 1, 0.01))[101] > warn_extreme_values*quantile(na.omit(data[[num_var_names[i]]]),probs = seq(0, 1, 0.01))[100]
if(d1){cat('Warning : Suspect extreme values in left tail')}
if(d99){cat('Warning : Suspect extreme values in right tail')}
```
``` {r eval=TRUE, fig.width=6, fig.height=2}
library(ggplot2)
v <- num_var_names[i]
hp <- ggplot(na.omit(data), aes_string(x=v)) + geom_histogram( colour="grey", fill="grey", binwidth=diff(range(na.omit(data[[v]]))/100))
hp + theme(axis.title.x = element_blank(),axis.text.x = element_text(size=10)) + theme(axis.title.y = element_blank(),axis.text.y = element_text(size=10))
```
see my datamineR package on github
https://github.com/hugokoopmans/dataMineR
As an addition to Hugo's excellent answer, I believe that in 2016 you need to include a print command as well:
```{r run-numeric-md, include=FALSE}
out = NULL
for (i in c(1:num_vars)) {
out = c(out, knit_child('da-numeric.Rmd'))
}
`r paste(out, collapse = '\n')`
```
For knitting Rmd to HTML, I find it more convenient to have a list of figures. In this case I get the desirable output with results='hide' as follows:
---
title: "Make a list of figures and show it"
output:
html_document
---
```{r}
suppressPackageStartupMessages({
library(ggplot2)
library(dplyr)
requireNamespace("scater")
requireNamespace("SingleCellExperiment")
})
```
```{r}
plots <- function() {
print("print")
cat("cat")
message("message")
warning("warning")
# These calls generate unwanted text
scater::mockSCE(ngene = 77, ncells = 33) %>%
scater::logNormCounts() %>%
scater::runPCA() %>%
SingleCellExperiment::reducedDim("PCA") %>%
as.data.frame() %>%
{
list(
f12 = ggplot(., aes(x = PC1, y = PC2)) + geom_point(),
f22 = ggplot(., aes(x = PC2, y = PC3)) + geom_point()
)
}
}
```
```{r, message=FALSE, warning=TRUE, results='hide'}
plots()
```
Only the plots are shown and the warnings (which you can switch off, as well).
Rookie question, I think.
I'm just trying to replicate this:
http://rpubs.com/gallery/googleVis
Open a new markdown document (in Rstudio), paste:
suppressPackageStartupMessages(library(googleVis))
T <- gvisTable(Exports, options = list(width = 200, height = 280))
G <- gvisGeoChart(Exports, locationvar = "Country", colorvar = "Profit",
options = list(width = 360, height = 280, dataMode = "regions"))
TG <- gvisMerge(T, G, horizontal = TRUE, tableOptions = "bgcolor=\"#CCCCCC\" cellspacing=10")
print(TG, "chart")
Between the ```{r} tags.
The resulting output (from the print function) is just the javascript (I think) code. It's not actually drawing the plot, in the preview window or the online version after publishing.
Is something else needed in the markdown? Like:
```{r something=something}
To get it to interpret the output from the print command properly?
Thanks
ANSWER
```{r anythingyoulike, results='asis'}
The top of this post
http://rpubs.com/gallery/googleVis really should point that out imo...
something like ```{r results='asis'}. However I don't have knitr manual with me now so you need to check.