Say I have the following code in knitr. How can I run it multiple times with different values of i?
```{r, echo=FALSE}
i<-0.1
```
### X,Y plot of Y=X+e where e is a standard normal distro: mean=0, sd=`r i`
```{r, echo=FALSE}
r<-rnorm(100,mean=0,sd=i)
x<-seq(0,1,length.out=100)
y<-x+r
plot(x,y)
```
EDIT:
As has been suggested ... I tried to do something like this: start a loop in an R code block, have a template in between and then close the loop -- R throws and error.
```{r, echo=FALSE}
for (i in 1:4) {
```
# bla
```{r, echo=FALSE}
}
```
What makes this question tricky is that not only the chunk content (the plot) must be repeated, but the heading as well. That's why we can neither simply reuse the chunk nor just loop over the plot command like
for (i in 1:3) { plot(rnorm(100, sd = i)) }
But it's almost that simple: We loop over the code that produces the plot and output the heading from inside the loop. This requires the chunk option results="asis" and cat to get verbatim markdown output:
```{r, echo=FALSE, results = "asis"}
sdVec <- c(0.1, 0.2, 0.3)
for (sd in sdVec) {
cat(sprintf("\n### X,Y plot of Y=X+e where e ~ N(0, %s)", sd))
r<-rnorm(100,mean=0,sd=sd)
x<-seq(0,1,length.out=100)
y<-x+r
plot(x,y)
}
```
See this answer for related issues.
Related
When I knit a document containing multiple plots obtained through purrr:map function, I get text slides in between each plot slide containing unwanted list index information (see image slides 2, 4, and 6). I'd like to remove these and just have plots.
I've tried results = "hide" and results = FALSE in the header.
These just return one plot instead of many, AND the text is still
there.
I've tried adding invisible() around my code as recommended
here. I don't see a difference.
How can I remove these and just have three slides with the three plots with no text?
---
title: "Reprex"
output: powerpoint_presentation
---
```{r include=FALSE}
library(tidyverse)
```
```{r echo=FALSE, results = FALSE}
ys <- c("mpg","cyl","disp")
ys %>% map(function(y)
invisible(ggplot(mtcars, aes(hp)) + geom_point(aes_string(y=y))))
```
Try this:
To suppress the console output use purrr::walk instead of map. See e.g. https://chrisbeeley.net/?p=1198
To get each plot printed on a separate slide use results='asis' and add two newlines via cat('\n\n') after each plot.
---
title: "Reprex"
output: powerpoint_presentation
---
```{r include=FALSE}
library(tidyverse)
```
```{r echo=FALSE, results='asis'}
ys <- c("mpg","cyl","disp")
walk(ys, function(y) {
p <- ggplot(mtcars, aes(hp)) + geom_point(aes_string(y=y))
print(p)
cat('\n\n')
})
```
I can embed plots using just RMarkdown's {.tabset}
#### Heading {.tabset}
##### Subheading 1
```{r, echo=F}
df[[1]]
```
This produces individual tabs with the specified graphs (df is a list of graphs, calling df[[i]] produces a graph) in the preview pane (renders all the graphs inline in RStudio).
And I can generate just the tabs using a for loop.
```{r, results='asis', echo = FALSE}
for (i in 1:length(gg0)) {
cat("##### ",q$Subheading[i],"\n")
}
```
And this produces the desired output - the tabs with the names in the Subheading column.
However, I am stuck in trying to generate the graphs themselves using the for loop similar to how I did when I coded it manually.
Extending the above, I tried to generate the markdown that produced the initial output but the plot fails to generate (both in the inline markdown and preview).
```{r, results='asis', echo = FALSE}
for (i in 1:length(gg0)) {
cat("##### ",q$Subheading[i],"\n")
cat('```{r, echo=F} \n')
cat("gg0[[",i,"]]\n")
cat('``` \n')
}
```
Maybe I am missing a finer point regarding markdown? I have tried various patterns using cat (and even without)
I would prefer a RMarkdown solution but other solutions are just as welcome.
I played around a little and found a solution. You have to use print within the asis code chunk...
```{r}
library(ggplot2)
gg0 <- list()
gg0[[1]] <- ggplot(mtcars, aes(mpg, hp)) + geom_point()
gg0[[2]] <- ggplot(mtcars, aes(mpg, disp)) + geom_point()
gg0[[3]] <- ggplot(mtcars, aes(mpg, drat)) + geom_point()
headings <- c('hp','disp','drat')
```
#### Heading {.tabset}
```{r, results='asis', echo = FALSE}
for (i in 1:length(gg0)) {
cat("##### ",headings[i],"\n")
print(gg0[[i]])
cat('\n\n')
}
```
As an explanation, the cat command together with results='asis' produces the markdown code for a lower level headline and prints the ggplot graph afterwards. Since we used `{.tabset} in the parent headline, it creates the plots in separate tabs.
Adding both plot.new(), dev.off() inside the for loop solves the problem of adding all the figures in the last tab. See the complete solution here.
Is it possible to get a nonformated markdown text inside a code chunk? My goal is to diplay a description inside a for cycle. In the example below, such operation leads to splitting the code into two syntactically invalid chunks:
I am using for cycle here
```{r results='hide'}
for(i in 1:5){
foo()
```
There is a lot of interesting stuff inside
```{r results='hide'}
bar()
}
```
which would ideally generate:
I am using for cycle here
for(i in 1:5){
foo()
There is a lot of interesting stuff inside
bar()
}
Following advice from the comment by user2706569, you can define the code chunk once with a name and evaluate it. Then you can reuse the code chunk, but only echo the lines you want, and without evaluation.
Drawn from Yihui's examples...
The plots from the original evaluation are
shown, but the code is not echoed here. (To
omit all of the outputs, check out the
chunk options such as `include=FALSE`.)
```{r mychunk, echo=FALSE}
## 'ugly' code that I do not want to show
par(mar = c(4, 4, 0.1, 0.1), cex.lab = 0.95, cex.axis = 0.9,
mgp = c(2, 0.7, 0), tcl = -0.3)
plot(mtcars[, 1:2])
plot(mtcars[, 4:5])
```
Now describe the code as you wish without evaluation.
Here's the first and second lines from the original chunk.
```{r mychunk, echo=1:2, eval=FALSE}
```
Here's the third line.
```{r mychunk, echo=3, eval=FALSE}
```
Here's the fourth line.
```{r mychunk, echo=4, eval=FALSE}
```
Here's the fifth line.
```{r mychunk, echo=5, eval=FALSE}
```
I would like to reuse a child file from my parent Rmd after modifying my data. The code seems to work fine, but the first figures are stepped over and all figures are replaced by the last one.
Is there a way to force new filenames with each new call?
This is my Parent.Rmd
XParent
========
```{r Opts, echo=FALSE}
opts_chunk$set(fig.show='asis', fig.keep='all', fig.width=3, fig.height=4, options(digits = 2), dev='jpeg')
```
```{r XLoad}
read_chunk(lines = readLines('XCode.R'))
```
```{r ParentChunk}
```
First child call
---------------
#### NOTICE the data is OK but the figure corresponds to the second child call (Y axis = 1200)
```{r CallChild, child='XChild.Rmd'}
```
#### I now modify the dataframe
```{r}
df$dist <- df$dist * 10
```
Second child call
-----------------
As this is the last case, the figure agrees with the data:
```{r CallChild2, child='XChild.Rmd'}
```
This Child.Rmd
XChild
```{r CodeAndFigs}
```
and XCode.R
## #knitr ParentChunk
df <- cars
colMeans(df)
# Y axis' upper limit is 120
plot(cars)
## #knitr CodeAndFigs
colMeans(df)
plot(df)
The figure in the first child call has been replace by the second figure. I have tried playing with different fig.keep and fig.show options with no luck.
With the latest development version on Github (which will turn into knitr 1.3 very soon on CRAN), you can use the fig.path option to specify different figure paths for the child document in two parent chunks CallChild and CallChild2, e.g.
XParent
========
```{r Opts, echo=FALSE}
opts_chunk$set(fig.show='asis', fig.keep='all', fig.width=3, fig.height=4, options(digits = 2), dev='jpeg')
```
```{r XLoad}
read_chunk(lines = readLines('XCode.R'))
```
```{r ParentChunk}
```
First child call
---------------
#### NOTICE the data is OK but the figure corresponds to the second child call (Y axis = 1200)
```{r CallChild, child='XChild.Rmd', fig.path='figure/child-'}
```
#### I now modify the dataframe
```{r}
df$dist <- df$dist * 10
```
Second child call
-----------------
As this is the last case, the figure agrees with the data:
```{r CallChild2, child='XChild.Rmd', fig.path='figure/child2-'}
```
The child document will inherit options from its parent chunk, so the figure paths will no clash if the parent options are different.
I am trying to use the R-Markdown feature in R Studio where I was trying to print plots which are generated inside a function. This is a basic run down example of what I am trying to do.
**Test printing plots generated in a function**
================================================
``` {r fig.width=8, fig.height=4, warning=FALSE, eval=TRUE, message=FALSE, tidy=TRUE, dev='png', echo=FALSE, fig.show='hold', fig.align='center'}
dat <- data.frame(x=c(1:10),y=c(11:20),z=c(21:30),name=rep(c("a","b"),each=5))
library(ggplot2)
ex <- function(data){
plot(data[,1],data[,2])
plot(data[,1],data[,3])
}
for (i in 1:10){
t1 <- rbind(i,ex(dat))
}
t1
```
Those testing this code, please make sure to save it as ".Rmd" file and then run the knithtml() in RStudio toolbar. This code above works absolutely fine with the kind of html output I desire. However when I replace the base plotting function by ggplot based code, I cannot get the knithtml() to produce the ggplot output of the 10 plots that I got like before. The base plot code above is now replaced by the following code
p1 <- ggplot(data=data, aes(x=data[,1],y=data[,2]))
p1 <- p1+geom_point()
p1
Am I missing something very simple here.
VJ
There are two problems in your code:
ggplot doesn't recognize the data x and y data, bacause it works inside the data environment. You should give it the column names directly.
The code in yur loop doesn't make sense. You can't mix a plot with an index... (the reason it works with the base plot is through a side-effect) I've replaced it with the simple plot command.
The following will work:
**Test printing plots generated in a function**
================================================
``` {r fig.width=8, fig.height=4, warning=FALSE, eval=TRUE, message=FALSE, tidy=TRUE, dev='png', echo=FALSE, fig.show='hold', fig.align='center'}
dat <- data.frame(x=c(1:10),y=c(11:20),z=c(21:30),name=rep(c("a","b"),each=5))
library(ggplot2)
ex <- function(data){
p1 <- ggplot(data=data, aes(x=x,y=y))
p1 <- p1+geom_point()
return(p1)
}
for (i in 1:2){
plot(ex(dat))
}
```