Introduction to plume

The goal of the plume package is to make the handling and formatting of author data for scientific writing in R Markdown and Quarto easy and (almost) painless.

Example data

We’ll use the data sets encyclopedists and encyclopedists_fr to explore the different functionalities of the package. These data sets contain information on four famous authors of the “Encyclopédie”, published in France in the 18th century. encyclopedists_fr is the French translation of encyclopedists and will be used to illustrate how to handle custom variable names. Both data sets are documented in ?encyclopedists.

encyclopedists
#> # A tibble: 4 × 12
#>   given_name family_name email phone orcid role_n1 role_n2 role_v1 role_v2 note 
#>   <chr>      <chr>       <chr> <chr> <chr> <chr>   <chr>   <chr>   <chr>   <chr>
#> 1 Denis      Diderot     dide… 00 0… 0000… Writing Superv… contri… superv… born…
#> 2 Jean-Jacq… Rousseau    rous… <NA>  0000… Writing <NA>    contri… <NA>    <NA> 
#> 3 François-… Arouet      arou… <NA>  <NA>  Writing <NA>    contri… <NA>    also…
#> 4 Jean       Le Rond d'… alem… <NA>  0000… Writing Superv… contri… superv… born…
#> # ℹ 2 more variables: affiliation1 <chr>, affiliation2 <chr>

Creating a plume object

plume provides two R6 classes, namely Plume and PlumeQuarto. To create a plume object, simply write the name of the class you want to use followed by the new() method. plume classes take a data frame or tibble as input data. The input data must have at least two columns named given_name and family_name.

Plume$new(encyclopedists)
#> # A tibble: 4 × 11
#>      id given_name     family_name literal_name initials email phone orcid note 
#>   <int> <chr>          <chr>       <chr>        <chr>    <chr> <chr> <chr> <chr>
#> 1     1 Denis          Diderot     Denis Dider… DD       dide… 00 0… 0000… born…
#> 2     2 Jean-Jacques   Rousseau    Jean-Jacque… J-JR     rous… <NA>  0000… <NA> 
#> 3     3 François-Marie Arouet      François-Ma… F-MA     arou… <NA>  <NA>  also…
#> 4     4 Jean           Le Rond d'… Jean Le Ron… JLRd'A   alem… <NA>  0000… born…
#> # ℹ 2 more variables: affiliation <list>, role <list>

Available names

The default variables handled by plume classes are organised into six categories:

Primaries: variables required to create a plume object.

Name Plume PlumeQuarto
given_name
family_name

Secondaries: optional variables that can be provided in the input data.

Name Plume PlumeQuarto
email
phone
fax
url
number
dropping_particle
acknowledgements

Nestables: optional variables that can be provided in the input data to pass multiple independent values to authors. Nestable variables must start with the same prefix. E.g. affiliation_1, affiliation_2, …, affiliation_n to pass several affiliations to authors.

Name Plume PlumeQuarto
affiliation
role
note

Constants: optional names that can be provided in the input data. These names are standardised and must be provided as is.

Name Plume PlumeQuarto
orcid
conceptualization
data_curation
analysis
funding
investigation
methodology
administration
resources
software
supervision
validation
visualization
writing
editing

Internals: variables created internally. These variables don’t need to be provided in the input data and are ignored if supplied. You shouldn’t worry much about these variables unless you want to customise names or extend plume classes with new default names.

Name Plume PlumeQuarto
id
initials
literal_name
corresponding
deceased
equal_contributor

Meta: PlumeQuarto-specific variables used to pass extra information that doesn’t fit in other categories. Meta columns must start with the prefix meta- and are followed by a custom name (e.g. meta-custom_name). You should only use these variables to pass data that are template specific. See Quarto’s arbitrary-metadata section for details.

Using custom names

plume lets you use custom variable names. Simply provide the names parameter a named vector when instantiating a plume class, where keys are default names and values their respective replacements.

Plume$new(
  encyclopedists_fr,
  names = c(
    given_name = "prénom",
    family_name = "nom",
    literal_name = "nom_complet",
    email = "courriel",
    initials = "initiales",
    role = "role_v"
  )
)
#> # A tibble: 4 × 10
#>      id prénom      nom   nom_complet initiales courriel orcid note  affiliation
#>   <int> <chr>       <chr> <chr>       <chr>     <chr>    <chr> <chr> <list>     
#> 1     1 Denis       Dide… Denis Dide… DD        diderot… 0000… né e… <tibble>   
#> 2     2 Jean-Jacqu… Rous… Jean-Jacqu… J-JR      roussea… 0000… <NA>  <tibble>   
#> 3     3 François-M… Arou… François-M… F-MA      arouet@… <NA>  dit … <tibble>   
#> 4     4 Jean        Le R… Jean Le Ro… JLRd'A    alember… 0000… né e… <tibble>   
#> # ℹ 1 more variable: role_v <list>

Pushing data into YAML headers

PlumeQuarto allows you to inject author metadata directly into the YAML header of .qmd files.

Consider the following Quarto document:

---
title: Encyclopédie
---

Qui scribit bis legit

You can push information from the input data into the YAML header using the to_yaml() method:

aut <- PlumeQuarto$new(
  dplyr::slice(encyclopedists, 1, 4),
  file = "file.qmd",
  names = c(role = "role_n")
)
aut$to_yaml()
---
title: Encyclopédie
author:
  - id: aut1
    name:
      given: Denis
      family: Diderot
    email: diderot@encyclopediste.fr
    phone: 00 00 00 01
    orcid: 0000-0000-0000-0001
    note: born in 1713 in Langres
    roles:
      - writing
      - supervision
    affiliations:
      - ref: aff1
  - id: aut2
    name:
      given: Jean
      family: Le Rond d'Alembert
    email: alembert@encyclopediste.fr
    orcid: 0000-0000-0000-0003
    note: born in 1717 in Paris
    roles:
      - writing
      - supervision
    affiliations:
      - ref: aff1
      - ref: aff2
affiliations:
  - id: aff1
    name: Université de Paris
  - id: aff2
    name: Collège des Quatre-Nations
---

Qui scribit bis legit

Authors are listed in the order they’re defined in the input data.

If the YAML header already has an author and affiliations keys, to_yaml() replaces old values with new ones.

aut <- PlumeQuarto$new(
  dplyr::slice(encyclopedists, 2),
  file = "file.qmd",
  names = c(role = "role_n")
)
aut$to_yaml()
---
title: Encyclopédie
author:
  - id: aut1
    name:
      given: Jean-Jacques
      family: Rousseau
    email: rousseau@encyclopediste.fr
    orcid: 0000-0000-0000-0002
    roles:
      - writing
    affiliations:
      - ref: aff1
affiliations:
  - id: aff1
    name: Lycée Louis-le-Grand
---

Qui scribit bis legit

Assigning status to authors

plume provides three methods to set particular status to authors:

set_equal_contributor() and set_deceased() are specific to PlumeQuarto. You can specify equal contributors and deceased authors in Plume via the note variable.

By default, set_*() methods assign values by authors’ id. You can change this behaviour at the object (in PlumeQuarto only) or method level using the by parameter.

Note that these methods are case insensitive.

aut <- Plume$new(dplyr::select(encyclopedists, given_name, family_name))

aut$set_corresponding_authors(dd, "j-jr", by = "initials")
aut
#> # A tibble: 4 × 6
#>      id given_name     family_name        literal_name    initials corresponding
#>   <int> <chr>          <chr>              <chr>           <chr>    <lgl>        
#> 1     1 Denis          Diderot            Denis Diderot   DD       TRUE         
#> 2     2 Jean-Jacques   Rousseau           Jean-Jacques R… J-JR     TRUE         
#> 3     3 François-Marie Arouet             François-Marie… F-MA     FALSE        
#> 4     4 Jean           Le Rond d'Alembert Jean Le Rond d… JLRd'A   FALSE

Use everyone() to assign TRUE to all authors:

aut$set_corresponding_authors(everyone())
aut
#> # A tibble: 4 × 6
#>      id given_name     family_name        literal_name    initials corresponding
#>   <int> <chr>          <chr>              <chr>           <chr>    <lgl>        
#> 1     1 Denis          Diderot            Denis Diderot   DD       TRUE         
#> 2     2 Jean-Jacques   Rousseau           Jean-Jacques R… J-JR     TRUE         
#> 3     3 François-Marie Arouet             François-Marie… F-MA     TRUE         
#> 4     4 Jean           Le Rond d'Alembert Jean Le Rond d… JLRd'A   TRUE

Or its variant everyone_but() to assign TRUE to all but specific authors:

aut$set_corresponding_authors(everyone_but(jean), by = "given_name")
aut
#> # A tibble: 4 × 6
#>      id given_name     family_name        literal_name    initials corresponding
#>   <int> <chr>          <chr>              <chr>           <chr>    <lgl>        
#> 1     1 Denis          Diderot            Denis Diderot   DD       TRUE         
#> 2     2 Jean-Jacques   Rousseau           Jean-Jacques R… J-JR     TRUE         
#> 3     3 François-Marie Arouet             François-Marie… F-MA     TRUE         
#> 4     4 Jean           Le Rond d'Alembert Jean Le Rond d… JLRd'A   FALSE

Getting author information

get_*() methods format author information into character vectors. This is useful if you want to output author data in a document without using journal templates.

Author lists

get_author_list() generates author lists. You can control the formatting of author suffixes (symbols linking authors to affiliations, notes and other metadata) using the format parameter. format takes a character string as argument and allows you to choose which symbol categories to suffix authors with, using the following keys:

The order of the keys determines the order of symbol categories.

aut <- Plume$new(encyclopedists)
aut$set_corresponding_authors(everyone())

aut$get_author_list(format = "ac") |> enumerate(last = ",\n")
#> Denis Diderot1\*, Jean-Jacques Rousseau2\*, François-Marie Arouet2\*,
#> Jean Le Rond d'Alembert1,3\*

aut$get_author_list(format = "ca") |> enumerate(last = ",\n")
#> Denis Diderot\*1, Jean-Jacques Rousseau\*2, François-Marie Arouet\*2,
#> Jean Le Rond d'Alembert\*1,3

In addition, you can use ^ to superscript and , to separate symbols:

aut$set_corresponding_authors(1, 4)

aut$get_author_list(format = "^a,^cn") |> enumerate(last = ",\n")
#> Denis Diderot^1,^\*†, Jean-Jacques Rousseau^2^, François-Marie Arouet^2^‡,
#> Jean Le Rond d'Alembert^1,3,^\*§

Use format = NULL or format = "" to ignore suffixes:

aut$get_author_list(format = NULL) |> enumerate()
#> Denis Diderot, Jean-Jacques Rousseau, François-Marie Arouet and Jean Le Rond d'Alembert

Affiliations & notes

get_affiliations() and get_notes() return authors’ affiliations and notes.

aut$get_affiliations()
#> ^1^Université de Paris
#> ^2^Lycée Louis-le-Grand
#> ^3^Collège des Quatre-Nations

aut$get_notes(sep = ": ", superscript = FALSE)
#> †: born in 1713 in Langres
#> ‡: also known as Voltaire
#> §: born in 1717 in Paris

ORCIDs

get_orcids() returns authors with their respective ORCID.

aut$get_orcids(compact = FALSE, icon = FALSE, sep = " ")
#> Denis Diderot <https://orcid.org/0000-0000-0000-0001>
#> Jean-Jacques Rousseau <https://orcid.org/0000-0000-0000-0002>
#> Jean Le Rond d'Alembert <https://orcid.org/0000-0000-0000-0003>

Contact details

You can get contact details of corresponding authors using the get_contact_details() method:

aut$get_contact_details()
#> diderot@encyclopediste.fr (Denis Diderot)
#> alembert@encyclopediste.fr (Jean Le Rond d'Alembert)

aut$get_contact_details(phone = TRUE)
#> diderot@encyclopediste.fr, 00 00 00 01 (Denis Diderot)
#> alembert@encyclopediste.fr (Jean Le Rond d'Alembert)

aut$get_contact_details(format = "{name}: {details}")
#> Denis Diderot: diderot@encyclopediste.fr
#> Jean Le Rond d'Alembert: alembert@encyclopediste.fr

Contributions

plume provides a convenient way to generate contribution lists using the get_contributions() method.

aut <- Plume$new(encyclopedists, names = c(role = "role_n"))
aut$get_contributions()
#> Writing: D.D., J.-J.R., F.-M.A. and J.L.R.d'A.
#> Supervision: D.D. and J.L.R.d'A.

aut$get_contributions(
  roles_first = FALSE,
  by_author = TRUE,
  literal_names = TRUE
)
#> Denis Diderot: Writing and Supervision
#> Jean-Jacques Rousseau: Writing
#> François-Marie Arouet: Writing
#> Jean Le Rond d'Alembert: Writing and Supervision

aut_v <- Plume$new(encyclopedists, names = c(role = "role_v"))
aut_v$get_contributions(roles_first = FALSE, divider = " ")
#> D.D., J.-J.R., F.-M.A. and J.L.R.d'A. contributed to the Encyclopédie
#> D.D. and J.L.R.d'A. supervised the project

By default, get_contributions() lists contributors in the order they’re defined. You can arrange contributors in alphabetical order with alphabetical_order = TRUE:

aut$get_contributions(alphabetical_order = TRUE)
#> Writing: D.D., F.-M.A., J.-J.R. and J.L.R.d'A.
#> Supervision: D.D. and J.L.R.d'A.

Symbols

Default symbols are:

#> List of 3
#>  $ affiliation  : NULL
#>  $ corresponding: chr "\\*"
#>  $ note         : chr [1:6] "†" "‡" "§" "¶" "#" "\\*\\*"

You can change symbols when creating a plume object using the parameter symbols.

Use NULL to display numbers:

aut <- Plume$new(encyclopedists, symbols = list(affiliation = letters, note = NULL))

aut$get_author_list(format = "^a,n^") |> enumerate(last = ",\n")
#> Denis Diderot^a,1^, Jean-Jacques Rousseau^b^, François-Marie Arouet^b,2^,
#> Jean Le Rond d'Alembert^a,c,3^

Use NULL as much as possible for symbols using numerous unique items (typically affiliations). If you have to use letters for a given category that has more unique items than letters, you can control the sequencing behaviour using the sequential() modifier, as shown below:

Plume$new(
  encyclopedists,
  symbols = list(affiliation = sequential(letters))
)

By default, plume repeats elements when all elements in a vector are consumed. Using sequential() allows you to display a logical sequence of characters (e.g. a, b, c, ..., z, aa, ab, ac, ..., az, ba, bb, bc, ...).

Outputting as markdown content

To output author data as markdown content, use the chunk option results: asis in combination with cat():

```{r}
#| results: asis
aut$get_contributions() |> cat(sep = "; ")
```

Inline chunks output values “as is” by default and can be used as follows:

`r aut$get_contact_details()`