21
votes

I have a project folder, which is my working directory. Let's call it project. Under the project folder are 4 subdirectories: code, data, figures, and documents.

I would like to put my .Rmd file in the code subdirectory. I would like the figures to go into the figures subdirectory. I would like the .html, .md, and .docx file(s) to go into the documents subdirectory. I would like to read in my data from the data subdirectory. Is this organizational structure possible? I can't seem to get it to work.

I start with this to set the working directory to project because I understand that knitr looks to the folder with the .Rmd file and treats it as the working directory if this is not specified.

```{r setglobal, cache = FALSE, include = TRUE}
library(knitr)
opts_knit$set(root.dir = "..")
```

Then I try setting the figure path relative to the working directory.

```{r setchunk, cache=FALSE, include=TRUE}
opts_chunk$set(fig.path = "./figures/")
getwd()
```

The working directory is correctly reported as project. The data is correctly read from the data subdirectory. All output is rendered properly and all code runs.

```{r readdata}
crctx <- readRDS("./data/crctx.rds")
getwd()
*run lots of analyses here*
```

But the figures end up in the project/code/figures directory instead of project/figures.

I have also tried setting base.dir but that doesn't seem to change anything. I added the parameter

base.dir = "./figures" 

to the opts_knit$set list. I even tried hard-coding the full path. But nothing seems to be able to change this.

I am using R 3.10 and RStudio 0.98.953. This is Mac 0SX 10.9.4.

Am I missing something? And is there a way to put the output files in their own directory?

The reason this is important is that I would like our company to all use the same directory structure, and this will allow us to organize our projects better.

Thanks in advance for any help.

Update:

I realize that opts_chunk$set(fig.path = "./figures/") is incorrect. I assumed that setting the root directory to the project folder using opts_knit$set(root.dir = normalizePath("../")) would make a global change to knitr, since that is what it is supposed to do. And it does work for the data subdirectory, which can now be accessed with "./data" which allows the code to run. However, the global setting doesn't apply to the figure output. Therefore, the correct specification is opts_chunk$set(fig.path = "../figures/") -- using ../ instead of ./. I think Richie Cotton fixed this, and I didn't quite see it for a while.

I also used Terminal in OSX to create a symbolic link from project/documents to project/code/figure which is created by default by knitr. With this, knitr looks to the right sub-subdirectory, but everything ends up in projects/documents. That worked really well. I can't get R do create the symbolic link properly using file.symlink. But it works fine in Terminal. Go figure.

update 2:

I got the output files to work as well. You have to use the knit command directly. The text is below.

Knitr code to knit a markdown document with .Rmd in code/analysis and output in output/reports: knit("./code/knitr_file.Rmd", "./documents/knitr_output.md”)

Pandoc code to convert .md file to .docx -- uses the same folder as the .md file pandoc("./documents/knitr_output.md", format = "docx”)

output styles (from knitr documentation)

pandoc('knitr_output.md', format='html') # HTML pandoc('knitr_output.md', format='latex') # LaTeX/PDF pandoc('knitr_output.md', format='docx') # MS Word pandoc('knitr_output.md', format='odt') # OpenDocument

2
See if normalizePath works for you.Eric Green
I looked at the syntax, and I couldn't figure out what that was supposed to do. But I can take another look.Mark Danese
An old question but this may help stackoverflow.com/a/51144177/4241780, it shows how to set the working directory to the main project folder when knitting.JWilliman

2 Answers

8
votes

Try this. It assumes you have the 4 folders you listed inside the working directory project. It also assumes you have a .csv file called myData.csv in data.

When you knit the file, the plot will be saved in figures. At the end, the code looks for html files in code and moves them to documents. There's probably a better way to do this.

```{r setup}
  library(knitr)
  opts_knit$set(root.dir=normalizePath('../'))
  opts_chunk$set(fig.path = "../figures/", dev='pdf') # corrected path and added dev
```

```{r import}
  dat <- read.csv("data/myData.csv")
```

```{r plot}
  # pdf(file="figures/test.pdf")  # I do this in setup instead
  plot(dat)
  # dev.off()
```

```{r move}
  files <- list.files("code/")
  index <- grep("html", files)
  file.rename(file.path("code", files[index]),
              file.path("documents", files[index]))
```
0
votes

I use this approach. Place this at the start of your rmd file, and you will be able to use run code in line and using an RStudio project setup. The trick is to reset the knitr home directory to your project directory (mine is a couple in from the project directory hence the '/../../' but you get the idea). You also need to reset the figure and cache pathways otherwise outputs will end up in strange places.

If you play around with the setup below you can create the right file structure for your project needs.

```{r setup, include=FALSE}
###--- Update the knitr working directory (R works from the project folder, knitr works in the rmd folder)
dd <- getwd()
knitr::opts_knit$set(root.dir= paste(dd,'/../../')) 

###--- Set some knitr defaults for all of the code blocks below. 
knitr::opts_chunk$set(warning=FALSE
                      ,error=FALSE
                      ,message=FALSE
                      ,cache=F
                      ,eval=TRUE
                      ,results='asis'
                      ,echo=TRUE
                      ,fig.ext="png"
                      ,cache.path = paste0(dd,'/cache/')
                      ,fig.path = paste0(dd,'/figures/')
                      ) 
```