user101089
user101089

Reputation: 3992

knitr: source() a file in a child document --- working directory changed

I ran into an unexpected problem trying to source a file containing some functions in a child document of a knitr .Rnw file. My directory structure is

CARME2015.Rnw  -- main file
  /frames
  /examples
  /fig
...

The main file contains this chunk:

<<odds, child="frames/odds.Rnw">>=
@

In a child file, ./frames/odds.Rnw, I had the following chunk:

<<hv-setup, include=FALSE >>=
source("examples/odds.R")
@

Running knitr under RStudio gave this error:

> knit2pdf("CARME2015.Rnw", quiet = TRUE)
processing file: ./frames/intro.Rnw
processing file: ./frames/ucb-ex.Rnw
processing file: ./frames/odds.Rnw
Quitting from lines 2-9 (./frames/odds.Rnw) 
Quitting from lines 78-93 (./frames/odds.Rnw) 
Error in file(filename, "r", encoding = encoding) : 
  cannot open the connection

I finally realized that the child= chunk option must reset the current working directory to that containing the child file, so the following did work to include my R file:

<<hv-setup, include=FALSE >>=
source("../examples/odds.R")
@

I wonder if this should be considered a bug or a 'feature'? In LaTeX, paths to included files are always considered relative to the document root directory, e.g.,

\includegraphics{fig/myfig}

will work anywhere within the document file structure.

(Related topic: knitr: child document in different directory)

Upvotes: 2

Views: 559

Answers (1)

CL.
CL.

Reputation: 14957

Whether you consider it a bug or a feature is up to you, but this behaviour is documented in ?knit:

The working directory when evaluating R code chunks is the directory of the input document by default […].

As child documents are just (RNW) "documents included in documents" it's quite natural that child documents get their own working directory.

The comparison to LaTeX is not valid, as there you input only fragments of a document, not a self-contained document. (Recall: The child document contains chunks not just the content of one chunk, that's what I mean by "self-contained" here.)

That said, this is how you can avoid problems that might occur due to the standard behaviour: In the main file, set root.dir to the current working directory.

main.Rnw:

\documentclass{article}
\begin{document}

<<>>=
library(knitr)
opts_knit$set(root.dir = getwd())

print(getwd())
@

<<child = "sub/child.Rnw">>=
@

\end{document}

sub/child.Rnw:

<<>>=
print(getwd())
@

This prints the same directory twice. If you skip the opts_knit, the child document is evaluated with the working directory set to sub.

Upvotes: 2

Related Questions