Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[FR] label chunk with an object #1419

Open
lidaidavid opened this issue Apr 3, 2023 · 5 comments
Open

[FR] label chunk with an object #1419

lidaidavid opened this issue Apr 3, 2023 · 5 comments
Assignees

Comments

@lidaidavid
Copy link

Hello. First of all I want to say thanks for the amazying work you all have been doing.
I want to cross-reference figures. In bookdown, this is done by @ref(fig:chunklabel). However, chunk labels have to be hand-written in each chunk, which is a pain sometimes.
Is there any way to give chunk labels from the value of an object? For example, if in an earlier chunk I have n = "good", can {r f(n)} mean the chunk is labeled "good"? Better yet, is it possible to give include_graphics() an option that would set a label for the figure so that bookdown can reference the figure with that label instead of the chunk label?
Thanks!

@yihui
Copy link
Member

yihui commented Apr 20, 2023

Is there any way to give chunk labels from the value of an object?

No, because the labels are determined before any code chunk is evaluated (i.e., they are determined at the parsing stage): https://github.com/yihui/knitr/blob/0e9bb8bc8cd77b2b8ace872637bb86a5b6d54bcb/R/parser.R#L197-L198 When parsing the document, the parser doesn't know the value of any objects.

Better yet, is it possible to give include_graphics() an option that would set a label for the figure so that bookdown can reference the figure with that label instead of the chunk label?

We could implement that, but it will add complexity to our code base, yet the benefit is not quite clear to me, i.e.,

```{r, label}
knitr::include_graphics('foo.png')
```

\@ref(fig:label)

vs

```{r, label}
knitr::include_graphics('foo.png', label = 'another')
```

\@ref(fig:another)

I fail to see the advantage of the latter way.

Anyway, thanks for the suggestion!

@lidaidavid
Copy link
Author

Thank you for your reply. I understand if this is too complexed. Unfortunately I know nothing about the code under the hood, so I'll take your word for it. I just want to explain why this may be something worth consideration.

I work with the package officedown to generate word documents for academic and coporate settings. After a few years of practice, I find it best to consider figures and tables to be external assets. That means to generate them in a separate .rmd file and save them to be .png or .rds to be later included in my main file.

I would also write two .csv files in which I input the meta data of the figures or tables, such as the url to this file, caption, footnote and so on. That way, in my main file I need only read the csv files and set a counter, then insert the figures and tables incrementally. For example, in the very beginning I would generate a dataframe such as this:

meta_data_figure <- read.csv("meta_data_figure.csv")
figure_counter <- 1

whereever I need insert a figure, I write something like:

knitr::include_graphics(meta_data_figure$url[figure_counter])
figure_counter <- figure_counter + 1

Then I don't have to pay any attention to the figures any further, no matter how many figures I need insert or whatever things I need to do to revise a figure.

This is superior to hand-written codes at each place because sometimes the meta data need revising, or the order need to change. I would then change things in the external .csv file without fooling around in my main document. For example, if I need to change the word "cognitive ability" to "intelligence", which is every where in my figure captions, I need only do that in the .csv files. This saves a lot of time.

All other chunk options can be input in the .csv file like this. I find the only inconsistent one is the chunk label which I would need for @ref(). I can't just add a column in my .csv file to be the label because as you said, it doesn't work like that. So in the main text I have to hand-write Figure 10. etc and change the numbering if I delete a figure. That's not very automatic like everything else I have set up to be.

Side note: I find R Markdown to be an incredibly useful tool but it needs a lot of tinkering to be used in an everday setting, because the audience we communicate with may not be as tech-savvy. For example, bibliography is cool, but my students cannot write their thesis with it because that would require a csl file that is compatible with the English/Chinese double styling required by the university, which officially CSL do not support. Using R Markdown is quite a hard sell in my experience.

Anyways, this might have been a moot point because @ref() doesn't work with officedown somehow but that is another issue. Thank you for everything you and your team have been doing!

@yihui
Copy link
Member

yihui commented Apr 21, 2023

I find the only inconsistent one is the chunk label which I would need for @ref(). I can't just add a column in my .csv file to be the label because as you said, it doesn't work like that. So in the main text I have to hand-write Figure 10. etc and change the numbering if I delete a figure. That's not very automatic like everything else I have set up to be.

I'm not very familiar with officedown, but if you use the @ref() feature in bookdown, figure numbers should be automatically generated. I don't understand why you need to hand-write them.

I also don't understand the advantage of putting the label in a csv file vs writing it directly in Rmd.

This is how bookdown currently works:

```{r, label}
knitr::include_graphics(meta_data_figure$url[1])
```

\@ref(fig:label)

These is what you proposed (if I understand you correctly, you want the chunk label to be dynamic):

```{r, label = meta_data_figure$label[1]}
knitr::include_graphics(meta_data_figure$url[1])
```

\@ref(fig:`r meta_data_figure$label[1]`)

or you want to be able to manually set a figure label in include_graphics():

```{r, label}
knitr::include_graphics(meta_data_figure$url[1], label = meta_data_figure$label[1])
```

\@ref(fig:`r meta_data_figure$label[1]`)

It's not clear to me what you found inconvenient or inefficient in the current bookdown approach.

For example, bibliography is cool, but my students cannot write their thesis with it because that would require a csl file that is compatible with the English/Chinese double styling required by the university, which officially CSL do not support.

They don't have use a CSL file if the thesis format is PDF, in which case a BibTeX style may suffice. If the format must be Word, then I don't know. I guess someone in your university has to create the CSL file. You might be able to find such a student. I know several universities have their LaTeX thesis templates created by volunteer students.

@lidaidavid
Copy link
Author

lidaidavid commented Apr 22, 2023

I'm sorry I digressed. Let's just focus on the advantage of putting the label in a csv file vs writing it directly in Rmd.

Say you have two figures that are 100 paragraphs away from each other, and now you need to switch their places. You have to scroll all the way up and down to copy and paste the labels.

Say you have several child documents that all contain different figures and now you need to switch two of them and you don't remember which child documents they are in. Even if you did, it is a hassle to find the child documents and copy/paste the codes.

Say you write a book with several chapters. Now half way through, you have forgotten the label of a previous figure because this isn't a super important thing to remember, and you name another figure with the same label. Now what would happen if you reference with that label? I understand now R Markdown allow two chunks to have the same label, but that doesn't solve the confusion when referencing chunks, am I correct? Better yet, why can't we use R to generate all the figure chunk labels(e.g. saved in a character vector so I can call it whenever I want)so we don't have to remember anything?

When I said the chunk label was not consistent, I meant it was not consistent with how I treated other attributes of a figure, such as caption, dimension, url and so on, because they are dynamic chunk options that will work if I read them from a csv, while the chunk label is not. It would be super efficient for my workflow if it were. I currently manage a journal that relies on R Markdown to generate the articles in an issue. It will save me a lot of time to manage all the figures in all the articles for an issue by using a csv, than rummaging through the original documents to find the right codes and copy paste between them.

Like I said, I don't know the codes under the hood, so I don't know how time-consuming it would be to make this happen. The current bookdown approach is OK, but I wouldn't say there is no room for improvement. If we could make the chunk label dynamic, people can write codes around that feature and come up with new ideas to make their lives easier. If you think it is not worthwhile, I trust your judgement.

@yihui
Copy link
Member

yihui commented Apr 22, 2023

Okay, I understand it now. Thanks a lot for the detailed explanation and examples! Let me think more about it and see what we can do.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
Status: Backlog
Development

No branches or pull requests

2 participants