├── _pkgdown.yml
├── docs
├── .nojekyll
├── reference
│ ├── tag_facets-1.png
│ ├── tag_facets-2.png
│ ├── tag_facets-3.png
│ ├── tag_facets-4.png
│ ├── tag_facets-5.png
│ ├── tag_facets-6.png
│ ├── tag_facets-7.png
│ ├── tag_facets-8.png
│ ├── figures
│ │ ├── README-example-1.png
│ │ └── README-unnamed-chunk-2-1.png
│ ├── index.html
│ └── tag_facets.html
├── pkgdown.yml
├── link.svg
├── bootstrap-toc.css
├── docsearch.js
├── pkgdown.js
├── 404.html
├── authors.html
├── bootstrap-toc.js
├── pkgdown.css
├── index.html
└── docsearch.css
├── .Rbuildignore
├── man
├── figures
│ ├── README-example-1.png
│ └── README-unnamed-chunk-2-1.png
├── get_layout.Rd
└── tag_facets.Rd
├── NAMESPACE
├── tagger.Rproj
├── R
├── zzzz.R
├── utils.R
└── tag-facet.R
├── DESCRIPTION
├── .gitignore
├── README.md
└── README.Rmd
/_pkgdown.yml:
--------------------------------------------------------------------------------
1 |
--------------------------------------------------------------------------------
/docs/.nojekyll:
--------------------------------------------------------------------------------
1 |
--------------------------------------------------------------------------------
/.Rbuildignore:
--------------------------------------------------------------------------------
1 | ^.*\.Rproj$
2 | ^\.Rproj\.user$
3 | ^README\.Rmd$
4 | ^_pkgdown\.yml$
5 | ^docs$
6 | ^pkgdown$
7 |
--------------------------------------------------------------------------------
/docs/reference/tag_facets-1.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/eliocamp/tagger/HEAD/docs/reference/tag_facets-1.png
--------------------------------------------------------------------------------
/docs/reference/tag_facets-2.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/eliocamp/tagger/HEAD/docs/reference/tag_facets-2.png
--------------------------------------------------------------------------------
/docs/reference/tag_facets-3.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/eliocamp/tagger/HEAD/docs/reference/tag_facets-3.png
--------------------------------------------------------------------------------
/docs/reference/tag_facets-4.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/eliocamp/tagger/HEAD/docs/reference/tag_facets-4.png
--------------------------------------------------------------------------------
/docs/reference/tag_facets-5.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/eliocamp/tagger/HEAD/docs/reference/tag_facets-5.png
--------------------------------------------------------------------------------
/docs/reference/tag_facets-6.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/eliocamp/tagger/HEAD/docs/reference/tag_facets-6.png
--------------------------------------------------------------------------------
/docs/reference/tag_facets-7.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/eliocamp/tagger/HEAD/docs/reference/tag_facets-7.png
--------------------------------------------------------------------------------
/docs/reference/tag_facets-8.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/eliocamp/tagger/HEAD/docs/reference/tag_facets-8.png
--------------------------------------------------------------------------------
/man/figures/README-example-1.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/eliocamp/tagger/HEAD/man/figures/README-example-1.png
--------------------------------------------------------------------------------
/docs/pkgdown.yml:
--------------------------------------------------------------------------------
1 | pandoc: 2.7.3
2 | pkgdown: 1.5.1
3 | pkgdown_sha: ~
4 | articles: []
5 | last_built: 2020-07-18T02:31Z
6 |
7 |
--------------------------------------------------------------------------------
/man/figures/README-unnamed-chunk-2-1.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/eliocamp/tagger/HEAD/man/figures/README-unnamed-chunk-2-1.png
--------------------------------------------------------------------------------
/docs/reference/figures/README-example-1.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/eliocamp/tagger/HEAD/docs/reference/figures/README-example-1.png
--------------------------------------------------------------------------------
/docs/reference/figures/README-unnamed-chunk-2-1.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/eliocamp/tagger/HEAD/docs/reference/figures/README-unnamed-chunk-2-1.png
--------------------------------------------------------------------------------
/NAMESPACE:
--------------------------------------------------------------------------------
1 | # Generated by roxygen2: do not edit by hand
2 |
3 | S3method(ggplot_add,tagger)
4 | S3method(ggplot_build,ggtagged)
5 | S3method(ggplot_gtable,ggplot_build_ggtagged)
6 | export(get_col)
7 | export(get_layout)
8 | export(get_row)
9 | export(get_tag)
10 | export(tag_facets)
11 | import(checkmate)
12 | importFrom(ggplot2,ggplot_add)
13 | importFrom(ggplot2,ggplot_build)
14 | importFrom(ggplot2,ggplot_gtable)
15 |
--------------------------------------------------------------------------------
/tagger.Rproj:
--------------------------------------------------------------------------------
1 | Version: 1.0
2 |
3 | RestoreWorkspace: Default
4 | SaveWorkspace: Default
5 | AlwaysSaveHistory: Default
6 |
7 | EnableCodeIndexing: Yes
8 | UseSpacesForTab: Yes
9 | NumSpacesForTab: 3
10 | Encoding: UTF-8
11 |
12 | RnwWeave: Sweave
13 | LaTeX: pdfLaTeX
14 |
15 | AutoAppendNewline: Yes
16 | StripTrailingWhitespace: Yes
17 |
18 | BuildType: Package
19 | PackageUseDevtools: Yes
20 | PackageInstallArgs: --no-multiarch --with-keep.source
21 | PackageRoxygenize: rd,collate,namespace
22 |
--------------------------------------------------------------------------------
/R/zzzz.R:
--------------------------------------------------------------------------------
1 | .onLoad <- function(libname, pkgname) {
2 | ggplot2::register_theme_elements(tagger.panel.tag.text = ggplot2::element_text(),
3 | tagger.panel.tag.background = ggplot2::element_rect(),
4 | element_tree = list(tagger.panel.tag.text = ggplot2::el_def("element_text", c("strip.text", "text")),
5 | tagger.panel.tag.background = ggplot2::el_def("element_rect", c("strip.background", "rect"))))
6 | }
7 |
8 |
--------------------------------------------------------------------------------
/DESCRIPTION:
--------------------------------------------------------------------------------
1 | Package: tagger
2 | Title: Adds tags to 'ggpot2' facets
3 | Version: 0.0.0.9000
4 | Authors@R:
5 | person(given = "Elio",
6 | family = "Campitelli",
7 | role = c("cre", "aut"),
8 | email = "elio.campitelli@cima.fcen.uba.ar",
9 | comment = c(ORCID = "0000-0002-7742-9230"))
10 | Description: Adds tags to 'ggplot2' facets with a single function and with native 'ggplot2' syntax.
11 | License: GPL-3
12 | Encoding: UTF-8
13 | Language: en
14 | LazyData: true
15 | Roxygen: list(markdown = TRUE)
16 | RoxygenNote: 7.2.3
17 | Imports:
18 | grDevices,
19 | gridtext,
20 | grid,
21 | ggplot2,
22 | gtable,
23 | checkmate
24 | Suggests:
25 | memoise
26 |
--------------------------------------------------------------------------------
/docs/link.svg:
--------------------------------------------------------------------------------
1 |
2 |
3 |
5 |
8 |
12 |
13 |
--------------------------------------------------------------------------------
/.gitignore:
--------------------------------------------------------------------------------
1 |
2 | # Created by https://www.toptal.com/developers/gitignore/api/r
3 | # Edit at https://www.toptal.com/developers/gitignore?templates=r
4 |
5 | ### R ###
6 | # History files
7 | .Rhistory
8 | .Rapp.history
9 |
10 | # Session Data files
11 | .RData
12 |
13 | # User-specific files
14 | .Ruserdata
15 |
16 | # Example code in package build process
17 | *-Ex.R
18 |
19 | # Output files from R CMD build
20 | /*.tar.gz
21 |
22 | # Output files from R CMD check
23 | /*.Rcheck/
24 |
25 | # RStudio files
26 | .Rproj.user/
27 |
28 | # produced vignettes
29 | vignettes/*.html
30 | vignettes/*.pdf
31 |
32 | # OAuth2 token, see https://github.com/hadley/httr/releases/tag/v0.3
33 | .httr-oauth
34 |
35 | # knitr and R markdown default cache directories
36 | *_cache/
37 | /cache/
38 |
39 | # Temporary files created by R markdown
40 | *.utf8.md
41 | *.knit.md
42 |
43 | # R Environment Variables
44 | .Renviron
45 |
46 | ### R.Bookdown Stack ###
47 | # R package: bookdown caching files
48 | /*_files/
49 |
50 | # End of https://www.toptal.com/developers/gitignore/api/r
51 | .Rproj.user
52 |
53 |
--------------------------------------------------------------------------------
/R/utils.R:
--------------------------------------------------------------------------------
1 | # # from ggplot2
2 | # plot_theme <- function(x, default = ggplot2::theme_get()) {
3 | # theme <- x$theme
4 | #
5 | # # apply theme defaults appropriately if needed
6 | # if (ggplot2:::is_theme_complete(theme)) {
7 | # # for complete themes, we fill in missing elements but don't do any element merging
8 | # # can't use `defaults()` because it strips attributes
9 | # missing <- setdiff(names(default), names(theme))
10 | # theme[missing] <- default[missing]
11 | # } else {
12 | # # otherwise, we can just add the theme to the default theme
13 | # theme <- default + theme
14 | # }
15 | #
16 | # # if we're still missing elements relative to fallback default, fill in those
17 | # missing <- setdiff(names(ggplot2:::ggplot_global$theme_default), names(theme))
18 | # theme[missing] <- ggplot2:::ggplot_global$theme_default[missing]
19 | #
20 | # # Check that all elements have the correct class (element_text, unit, etc)
21 | # if (ggplot2:::is_theme_validate(theme)) {
22 | # mapply(
23 | # ggplot2:::validate_element, theme, names(theme),
24 | # MoreArgs = list(element_tree = ggplot2::get_element_tree())
25 | # )
26 | # }
27 | #
28 | # theme
29 | # }
30 | #
31 |
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 | # tagger
5 |
6 |
7 |
8 |
9 |
10 | The goal of tagger is to easily add tags to facetted plots in order to
11 | identify panles.
12 |
13 | ## Installation
14 |
15 |
16 |
17 |
18 |
19 |
20 |
21 |
22 |
23 | You can install the development version from
24 | [GitHub](https://github.com/) with:
25 |
26 | ``` r
27 | # install.packages("devtools")
28 | devtools::install_github("eliocamp/tagger")
29 | ```
30 |
31 | ## Example
32 |
33 | In the default usage, you can simply add `tag_facets()` to add a tag to
34 | each panel of a ggplo2 plot.
35 |
36 | ``` r
37 | library(tagger)
38 | library(ggplot2)
39 |
40 | ggplot(mtcars, aes(hp, mpg)) +
41 | geom_point() +
42 | facet_grid(cyl ~ vs) +
43 | tag_facets()
44 | ```
45 |
46 |  If you want to tag rows
47 | and columns instead of each panel indivdually, you can set it with the
48 | `tag` argument.
49 |
50 | ``` r
51 | ggplot(mtcars, aes(hp, mpg)) +
52 | geom_point() +
53 | facet_grid(cyl ~ vs) +
54 | tag_facets(tag = "rc")
55 | ```
56 |
57 | 
58 |
--------------------------------------------------------------------------------
/README.Rmd:
--------------------------------------------------------------------------------
1 | ---
2 | output: github_document
3 | ---
4 |
5 |
6 |
7 | ```{r, include = FALSE}
8 | knitr::opts_chunk$set(
9 | collapse = TRUE,
10 | comment = "#>",
11 | fig.path = "man/figures/README-"
12 | )
13 | ```
14 |
15 | # tagger
16 |
17 |
18 |
19 |
20 | The goal of tagger is to easily add tags to facetted plots in order to identify panles.
21 |
22 | ## Installation
23 |
24 |
25 |
26 |
27 |
28 |
29 |
30 | You can install the development version from [GitHub](https://github.com/) with:
31 |
32 | ``` r
33 | # install.packages("devtools")
34 | devtools::install_github("eliocamp/tagger")
35 | ```
36 | ## Example
37 |
38 | In the default usage, you can simply add `tag_facets()` to add a tag to each panel of a ggplo2 plot.
39 |
40 | ```{r example}
41 | library(tagger)
42 | library(ggplot2)
43 |
44 | ggplot(mtcars, aes(hp, mpg)) +
45 | geom_point() +
46 | facet_grid(cyl ~ vs) +
47 | tag_facets()
48 | ```
49 | If you want to tag rows and columns instead of each panel indivdually, you can set it with the `tag` argument.
50 |
51 | ```{r}
52 | ggplot(mtcars, aes(hp, mpg)) +
53 | geom_point() +
54 | facet_grid(cyl ~ vs) +
55 | tag_facets(tag = "rc")
56 | ```
57 |
--------------------------------------------------------------------------------
/man/get_layout.Rd:
--------------------------------------------------------------------------------
1 | % Generated by roxygen2: do not edit by hand
2 | % Please edit documentation in R/tag-facet.R
3 | \name{get_layout}
4 | \alias{get_layout}
5 | \alias{get_tag}
6 | \alias{get_row}
7 | \alias{get_col}
8 | \title{Get labels asigned to each panel of a tagged plot}
9 | \usage{
10 | get_layout(plot = ggplot2::last_plot())
11 |
12 | get_tag(filter = TRUE, plot = ggplot2::last_plot(), n = 1)
13 |
14 | get_row(filter = TRUE, plot = ggplot2::last_plot(), n = 1)
15 |
16 | get_col(filter = TRUE, plot = ggplot2::last_plot(), n = 1)
17 | }
18 | \arguments{
19 | \item{plot}{a plot object}
20 |
21 | \item{filter}{an expression that, evaluated within the data used
22 | to generate the facets of the plot, evaluates to a logical vector
23 | or a sequence of rows.}
24 |
25 | \item{n}{number of expected panels.}
26 | }
27 | \value{
28 | \code{get_tags()}, \code{get_row()} and \code{get_col()} return a character vector
29 | of length \code{n} with the tags, unique rows or unique columns that meet
30 | the \code{filter} condition.
31 |
32 | \code{get_layout()} returns the full data.frame describing the panel layout.
33 | }
34 | \description{
35 | Get labels asigned to each panel of a tagged plot
36 | }
37 | \examples{
38 | library(ggplot2)
39 | g <- ggplot(mtcars, aes(hp, mpg)) +
40 | geom_point() +
41 | facet_grid(cyl ~ vs) +
42 | tag_facets("rc")
43 |
44 | # By default these functions retrieve tags from
45 | # the result of ggplo2::last_plot().
46 |
47 | # Get all tags
48 | get_layout()
49 |
50 | # Get one tag
51 | get_tag(cyl == 4 & vs == 0)
52 |
53 | # Get more than one tag
54 | get_tag(cyl == 4, n = 2)
55 |
56 |
57 | get_row(cyl == 4)
58 | get_col(vs == 0)
59 |
60 | # Use it with inline markdown to refer always to the correct panel:
61 | # "As you can see in panel `r get_tag(cyl == 4 & vs == 0)` ..."
62 |
63 | }
64 |
--------------------------------------------------------------------------------
/docs/bootstrap-toc.css:
--------------------------------------------------------------------------------
1 | /*!
2 | * Bootstrap Table of Contents v0.4.1 (http://afeld.github.io/bootstrap-toc/)
3 | * Copyright 2015 Aidan Feldman
4 | * Licensed under MIT (https://github.com/afeld/bootstrap-toc/blob/gh-pages/LICENSE.md) */
5 |
6 | /* modified from https://github.com/twbs/bootstrap/blob/94b4076dd2efba9af71f0b18d4ee4b163aa9e0dd/docs/assets/css/src/docs.css#L548-L601 */
7 |
8 | /* All levels of nav */
9 | nav[data-toggle='toc'] .nav > li > a {
10 | display: block;
11 | padding: 4px 20px;
12 | font-size: 13px;
13 | font-weight: 500;
14 | color: #767676;
15 | }
16 | nav[data-toggle='toc'] .nav > li > a:hover,
17 | nav[data-toggle='toc'] .nav > li > a:focus {
18 | padding-left: 19px;
19 | color: #563d7c;
20 | text-decoration: none;
21 | background-color: transparent;
22 | border-left: 1px solid #563d7c;
23 | }
24 | nav[data-toggle='toc'] .nav > .active > a,
25 | nav[data-toggle='toc'] .nav > .active:hover > a,
26 | nav[data-toggle='toc'] .nav > .active:focus > a {
27 | padding-left: 18px;
28 | font-weight: bold;
29 | color: #563d7c;
30 | background-color: transparent;
31 | border-left: 2px solid #563d7c;
32 | }
33 |
34 | /* Nav: second level (shown on .active) */
35 | nav[data-toggle='toc'] .nav .nav {
36 | display: none; /* Hide by default, but at >768px, show it */
37 | padding-bottom: 10px;
38 | }
39 | nav[data-toggle='toc'] .nav .nav > li > a {
40 | padding-top: 1px;
41 | padding-bottom: 1px;
42 | padding-left: 30px;
43 | font-size: 12px;
44 | font-weight: normal;
45 | }
46 | nav[data-toggle='toc'] .nav .nav > li > a:hover,
47 | nav[data-toggle='toc'] .nav .nav > li > a:focus {
48 | padding-left: 29px;
49 | }
50 | nav[data-toggle='toc'] .nav .nav > .active > a,
51 | nav[data-toggle='toc'] .nav .nav > .active:hover > a,
52 | nav[data-toggle='toc'] .nav .nav > .active:focus > a {
53 | padding-left: 28px;
54 | font-weight: 500;
55 | }
56 |
57 | /* from https://github.com/twbs/bootstrap/blob/e38f066d8c203c3e032da0ff23cd2d6098ee2dd6/docs/assets/css/src/docs.css#L631-L634 */
58 | nav[data-toggle='toc'] .nav > .active > ul {
59 | display: block;
60 | }
61 |
--------------------------------------------------------------------------------
/docs/docsearch.js:
--------------------------------------------------------------------------------
1 | $(function() {
2 |
3 | // register a handler to move the focus to the search bar
4 | // upon pressing shift + "/" (i.e. "?")
5 | $(document).on('keydown', function(e) {
6 | if (e.shiftKey && e.keyCode == 191) {
7 | e.preventDefault();
8 | $("#search-input").focus();
9 | }
10 | });
11 |
12 | $(document).ready(function() {
13 | // do keyword highlighting
14 | /* modified from https://jsfiddle.net/julmot/bL6bb5oo/ */
15 | var mark = function() {
16 |
17 | var referrer = document.URL ;
18 | var paramKey = "q" ;
19 |
20 | if (referrer.indexOf("?") !== -1) {
21 | var qs = referrer.substr(referrer.indexOf('?') + 1);
22 | var qs_noanchor = qs.split('#')[0];
23 | var qsa = qs_noanchor.split('&');
24 | var keyword = "";
25 |
26 | for (var i = 0; i < qsa.length; i++) {
27 | var currentParam = qsa[i].split('=');
28 |
29 | if (currentParam.length !== 2) {
30 | continue;
31 | }
32 |
33 | if (currentParam[0] == paramKey) {
34 | keyword = decodeURIComponent(currentParam[1].replace(/\+/g, "%20"));
35 | }
36 | }
37 |
38 | if (keyword !== "") {
39 | $(".contents").unmark({
40 | done: function() {
41 | $(".contents").mark(keyword);
42 | }
43 | });
44 | }
45 | }
46 | };
47 |
48 | mark();
49 | });
50 | });
51 |
52 | /* Search term highlighting ------------------------------*/
53 |
54 | function matchedWords(hit) {
55 | var words = [];
56 |
57 | var hierarchy = hit._highlightResult.hierarchy;
58 | // loop to fetch from lvl0, lvl1, etc.
59 | for (var idx in hierarchy) {
60 | words = words.concat(hierarchy[idx].matchedWords);
61 | }
62 |
63 | var content = hit._highlightResult.content;
64 | if (content) {
65 | words = words.concat(content.matchedWords);
66 | }
67 |
68 | // return unique words
69 | var words_uniq = [...new Set(words)];
70 | return words_uniq;
71 | }
72 |
73 | function updateHitURL(hit) {
74 |
75 | var words = matchedWords(hit);
76 | var url = "";
77 |
78 | if (hit.anchor) {
79 | url = hit.url_without_anchor + '?q=' + escape(words.join(" ")) + '#' + hit.anchor;
80 | } else {
81 | url = hit.url + '?q=' + escape(words.join(" "));
82 | }
83 |
84 | return url;
85 | }
86 |
--------------------------------------------------------------------------------
/man/tag_facets.Rd:
--------------------------------------------------------------------------------
1 | % Generated by roxygen2: do not edit by hand
2 | % Please edit documentation in R/tag-facet.R
3 | \name{tag_facets}
4 | \alias{tag_facets}
5 | \title{Adds tags to facets}
6 | \usage{
7 | tag_facets(
8 | tag = c("panel", "rc", "cr"),
9 | position = "tl",
10 | tag_levels = c("a", "1"),
11 | tag_pool = NULL,
12 | tag_prefix = "",
13 | tag_suffix = ")",
14 | tag_sep = "."
15 | )
16 | }
17 | \arguments{
18 | \item{tag}{Character indicating the element to tag. Possible values are
19 | \itemize{
20 | \item "panel": each single panels is individually tag.
21 | \item "rc": facets are tagged by row and then column.
22 | \item "cr": factes are tagged by columns and then row.
23 | }}
24 |
25 | \item{position}{Character indicating the position of the tag. Options are "tl"
26 | (top-left), "tr" (top-right), "br" (bottom-right) and "bl" (bottom-left).
27 | Alternatively, for finer control, it can be a list of elements "x", "u",
28 | "hjust" and "vjust" that define the position of the tag within each panel.}
29 |
30 | \item{tag_levels}{A character vector defining the enumeration format to use
31 | at each level. Possible values are \code{'a'} for lowercase letters, \code{'A'} for
32 | uppercase letters, \code{'1'} for numbers, \code{'i'} for lowercase Roman numerals, and
33 | \code{'I'} for uppercase Roman numerals. It can also be a list containing
34 | character vectors defining arbitrary tag sequences. If any element in the
35 | list is a scalar and one of \code{'a'}, \code{'A'}, \code{'1'}, \verb{'i}, or \code{'I'}, this level
36 | will be expanded to the expected sequence.}
37 |
38 | \item{tag_pool}{An optional character vector of user-defined "pool" of tags.
39 | If not \code{NULL}, it will be used instead of \code{tag_levels}. Should be at least
40 | as long as the total number of panels.}
41 |
42 | \item{tag_prefix, tag_suffix}{Strings that should appear before or after the
43 | tag.}
44 |
45 | \item{tag_sep}{A separator between different tag levels}
46 | }
47 | \description{
48 | Adds tags to facets
49 | }
50 | \details{
51 | Tags inherit aesthetic properties (size, font, colour, etc...) from strip.text and
52 | strip.background defined by \code{\link[ggplot2:theme]{ggplot2::theme()}}. For fine-grained detail, these can be
53 | overriden by setting tagger.panel.tag.text and tagger.panel.tag.background.
54 | }
55 | \examples{
56 |
57 | library(ggplot2)
58 | # Base plot
59 | g <- ggplot(mtcars, aes(hp, mpg)) +
60 | geom_point() +
61 | facet_grid(cyl ~ vs)
62 |
63 | g + tag_facets()
64 | g + tag_facets("rc")
65 | g + tag_facets("cr")
66 | g + tag_facets(position = "br")
67 | g + tag_facets("rc", tag_levels = c("A", "I"))
68 |
69 | # You can get finer control over position.
70 | g + tag_facets(position = list(x = 0.5, y = 0.5))
71 |
72 | g + tag_facets(tag_pool = c("one", "two", "three", "four", "five", "six"), tag_suffix = "")
73 | # Thanks to theme inheritance, tags should look aceptable
74 | # out of the box in any theme.
75 | g + tag_facets() +
76 | theme_dark()
77 |
78 | # But you can control their appearance and create your own atrocities
79 | g + tag_facets() +
80 | theme_dark() +
81 | theme(tagger.panel.tag.text = element_text(color = "red", size = 16),
82 | tagger.panel.tag.background = element_rect(fill = "purple"))
83 |
84 | }
85 |
--------------------------------------------------------------------------------
/docs/pkgdown.js:
--------------------------------------------------------------------------------
1 | /* http://gregfranko.com/blog/jquery-best-practices/ */
2 | (function($) {
3 | $(function() {
4 |
5 | $('.navbar-fixed-top').headroom();
6 |
7 | $('body').css('padding-top', $('.navbar').height() + 10);
8 | $(window).resize(function(){
9 | $('body').css('padding-top', $('.navbar').height() + 10);
10 | });
11 |
12 | $('[data-toggle="tooltip"]').tooltip();
13 |
14 | var cur_path = paths(location.pathname);
15 | var links = $("#navbar ul li a");
16 | var max_length = -1;
17 | var pos = -1;
18 | for (var i = 0; i < links.length; i++) {
19 | if (links[i].getAttribute("href") === "#")
20 | continue;
21 | // Ignore external links
22 | if (links[i].host !== location.host)
23 | continue;
24 |
25 | var nav_path = paths(links[i].pathname);
26 |
27 | var length = prefix_length(nav_path, cur_path);
28 | if (length > max_length) {
29 | max_length = length;
30 | pos = i;
31 | }
32 | }
33 |
34 | // Add class to parent
, and enclosing if in dropdown
35 | if (pos >= 0) {
36 | var menu_anchor = $(links[pos]);
37 | menu_anchor.parent().addClass("active");
38 | menu_anchor.closest("li.dropdown").addClass("active");
39 | }
40 | });
41 |
42 | function paths(pathname) {
43 | var pieces = pathname.split("/");
44 | pieces.shift(); // always starts with /
45 |
46 | var end = pieces[pieces.length - 1];
47 | if (end === "index.html" || end === "")
48 | pieces.pop();
49 | return(pieces);
50 | }
51 |
52 | // Returns -1 if not found
53 | function prefix_length(needle, haystack) {
54 | if (needle.length > haystack.length)
55 | return(-1);
56 |
57 | // Special case for length-0 haystack, since for loop won't run
58 | if (haystack.length === 0) {
59 | return(needle.length === 0 ? 0 : -1);
60 | }
61 |
62 | for (var i = 0; i < haystack.length; i++) {
63 | if (needle[i] != haystack[i])
64 | return(i);
65 | }
66 |
67 | return(haystack.length);
68 | }
69 |
70 | /* Clipboard --------------------------*/
71 |
72 | function changeTooltipMessage(element, msg) {
73 | var tooltipOriginalTitle=element.getAttribute('data-original-title');
74 | element.setAttribute('data-original-title', msg);
75 | $(element).tooltip('show');
76 | element.setAttribute('data-original-title', tooltipOriginalTitle);
77 | }
78 |
79 | if(ClipboardJS.isSupported()) {
80 | $(document).ready(function() {
81 | var copyButton = " ";
82 |
83 | $(".examples, div.sourceCode").addClass("hasCopyButton");
84 |
85 | // Insert copy buttons:
86 | $(copyButton).prependTo(".hasCopyButton");
87 |
88 | // Initialize tooltips:
89 | $('.btn-copy-ex').tooltip({container: 'body'});
90 |
91 | // Initialize clipboard:
92 | var clipboardBtnCopies = new ClipboardJS('[data-clipboard-copy]', {
93 | text: function(trigger) {
94 | return trigger.parentNode.textContent;
95 | }
96 | });
97 |
98 | clipboardBtnCopies.on('success', function(e) {
99 | changeTooltipMessage(e.trigger, 'Copied!');
100 | e.clearSelection();
101 | });
102 |
103 | clipboardBtnCopies.on('error', function() {
104 | changeTooltipMessage(e.trigger,'Press Ctrl+C or Command+C to copy');
105 | });
106 | });
107 | }
108 | })(window.jQuery || window.$)
109 |
--------------------------------------------------------------------------------
/docs/404.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 | Page not found (404) • tagger
10 |
11 |
12 |
13 |
14 |
15 |
16 |
17 |
18 |
19 |
20 |
21 |
22 |
23 |
24 |
25 |
26 |
27 |
28 |
29 |
30 |
31 |
32 |
33 |
34 |
35 |
36 |
37 |
38 |
39 |
40 |
41 |
42 |
43 |
44 |
45 |
46 |
47 |
48 |
49 |
50 |
51 |
55 |
56 |
57 |
58 |
59 |
60 |
61 |
62 |
63 |
97 |
98 |
99 |
100 |
101 |
102 |
103 |
104 |
107 |
108 | Content not found. Please use links in the navbar.
109 |
110 |
111 |
112 |
117 |
118 |
119 |
120 |
121 |
122 |
132 |
133 |
134 |
135 |
136 |
137 |
138 |
139 |
140 |
141 |
--------------------------------------------------------------------------------
/docs/authors.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 | Authors • tagger
10 |
11 |
12 |
13 |
14 |
15 |
16 |
17 |
18 |
19 |
20 |
21 |
22 |
23 |
24 |
25 |
26 |
27 |
28 |
29 |
30 |
31 |
32 |
33 |
34 |
35 |
36 |
37 |
38 |
39 |
40 |
41 |
42 |
43 |
44 |
45 |
46 |
47 |
48 |
49 |
50 |
51 |
55 |
56 |
57 |
58 |
59 |
60 |
61 |
62 |
63 |
97 |
98 |
99 |
100 |
101 |
102 |
103 |
104 |
107 |
108 |
114 |
115 |
116 |
117 |
118 |
119 |
120 |
121 |
131 |
132 |
133 |
134 |
135 |
136 |
137 |
138 |
139 |
140 |
--------------------------------------------------------------------------------
/docs/bootstrap-toc.js:
--------------------------------------------------------------------------------
1 | /*!
2 | * Bootstrap Table of Contents v0.4.1 (http://afeld.github.io/bootstrap-toc/)
3 | * Copyright 2015 Aidan Feldman
4 | * Licensed under MIT (https://github.com/afeld/bootstrap-toc/blob/gh-pages/LICENSE.md) */
5 | (function() {
6 | 'use strict';
7 |
8 | window.Toc = {
9 | helpers: {
10 | // return all matching elements in the set, or their descendants
11 | findOrFilter: function($el, selector) {
12 | // http://danielnouri.org/notes/2011/03/14/a-jquery-find-that-also-finds-the-root-element/
13 | // http://stackoverflow.com/a/12731439/358804
14 | var $descendants = $el.find(selector);
15 | return $el.filter(selector).add($descendants).filter(':not([data-toc-skip])');
16 | },
17 |
18 | generateUniqueIdBase: function(el) {
19 | var text = $(el).text();
20 | var anchor = text.trim().toLowerCase().replace(/[^A-Za-z0-9]+/g, '-');
21 | return anchor || el.tagName.toLowerCase();
22 | },
23 |
24 | generateUniqueId: function(el) {
25 | var anchorBase = this.generateUniqueIdBase(el);
26 | for (var i = 0; ; i++) {
27 | var anchor = anchorBase;
28 | if (i > 0) {
29 | // add suffix
30 | anchor += '-' + i;
31 | }
32 | // check if ID already exists
33 | if (!document.getElementById(anchor)) {
34 | return anchor;
35 | }
36 | }
37 | },
38 |
39 | generateAnchor: function(el) {
40 | if (el.id) {
41 | return el.id;
42 | } else {
43 | var anchor = this.generateUniqueId(el);
44 | el.id = anchor;
45 | return anchor;
46 | }
47 | },
48 |
49 | createNavList: function() {
50 | return $('');
51 | },
52 |
53 | createChildNavList: function($parent) {
54 | var $childList = this.createNavList();
55 | $parent.append($childList);
56 | return $childList;
57 | },
58 |
59 | generateNavEl: function(anchor, text) {
60 | var $a = $(' ');
61 | $a.attr('href', '#' + anchor);
62 | $a.text(text);
63 | var $li = $(' ');
64 | $li.append($a);
65 | return $li;
66 | },
67 |
68 | generateNavItem: function(headingEl) {
69 | var anchor = this.generateAnchor(headingEl);
70 | var $heading = $(headingEl);
71 | var text = $heading.data('toc-text') || $heading.text();
72 | return this.generateNavEl(anchor, text);
73 | },
74 |
75 | // Find the first heading level (``, then ``, etc.) that has more than one element. Defaults to 1 (for ``).
76 | getTopLevel: function($scope) {
77 | for (var i = 1; i <= 6; i++) {
78 | var $headings = this.findOrFilter($scope, 'h' + i);
79 | if ($headings.length > 1) {
80 | return i;
81 | }
82 | }
83 |
84 | return 1;
85 | },
86 |
87 | // returns the elements for the top level, and the next below it
88 | getHeadings: function($scope, topLevel) {
89 | var topSelector = 'h' + topLevel;
90 |
91 | var secondaryLevel = topLevel + 1;
92 | var secondarySelector = 'h' + secondaryLevel;
93 |
94 | return this.findOrFilter($scope, topSelector + ',' + secondarySelector);
95 | },
96 |
97 | getNavLevel: function(el) {
98 | return parseInt(el.tagName.charAt(1), 10);
99 | },
100 |
101 | populateNav: function($topContext, topLevel, $headings) {
102 | var $context = $topContext;
103 | var $prevNav;
104 |
105 | var helpers = this;
106 | $headings.each(function(i, el) {
107 | var $newNav = helpers.generateNavItem(el);
108 | var navLevel = helpers.getNavLevel(el);
109 |
110 | // determine the proper $context
111 | if (navLevel === topLevel) {
112 | // use top level
113 | $context = $topContext;
114 | } else if ($prevNav && $context === $topContext) {
115 | // create a new level of the tree and switch to it
116 | $context = helpers.createChildNavList($prevNav);
117 | } // else use the current $context
118 |
119 | $context.append($newNav);
120 |
121 | $prevNav = $newNav;
122 | });
123 | },
124 |
125 | parseOps: function(arg) {
126 | var opts;
127 | if (arg.jquery) {
128 | opts = {
129 | $nav: arg
130 | };
131 | } else {
132 | opts = arg;
133 | }
134 | opts.$scope = opts.$scope || $(document.body);
135 | return opts;
136 | }
137 | },
138 |
139 | // accepts a jQuery object, or an options object
140 | init: function(opts) {
141 | opts = this.helpers.parseOps(opts);
142 |
143 | // ensure that the data attribute is in place for styling
144 | opts.$nav.attr('data-toggle', 'toc');
145 |
146 | var $topContext = this.helpers.createChildNavList(opts.$nav);
147 | var topLevel = this.helpers.getTopLevel(opts.$scope);
148 | var $headings = this.helpers.getHeadings(opts.$scope, topLevel);
149 | this.helpers.populateNav($topContext, topLevel, $headings);
150 | }
151 | };
152 |
153 | $(function() {
154 | $('nav[data-toggle="toc"]').each(function(i, el) {
155 | var $nav = $(el);
156 | Toc.init($nav);
157 | });
158 | });
159 | })();
160 |
--------------------------------------------------------------------------------
/docs/reference/index.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 | Function reference • tagger
10 |
11 |
12 |
13 |
14 |
15 |
16 |
17 |
18 |
19 |
20 |
21 |
22 |
23 |
24 |
25 |
26 |
27 |
28 |
29 |
30 |
31 |
32 |
33 |
34 |
35 |
36 |
37 |
38 |
39 |
40 |
41 |
42 |
43 |
44 |
45 |
46 |
47 |
48 |
49 |
50 |
51 |
55 |
56 |
57 |
58 |
59 |
60 |
61 |
62 |
63 |
97 |
98 |
99 |
100 |
101 |
102 |
103 |
104 |
107 |
108 |
109 |
110 |
111 |
112 |
113 |
114 |
115 |
116 |
117 |
118 |
119 | All functions
120 |
121 |
122 |
123 |
124 |
125 |
126 |
127 |
128 |
129 |
130 |
131 | tag_facets()
132 |
133 | Adds tags to facets
134 |
135 |
136 |
137 |
138 |
139 |
144 |
145 |
146 |
147 |
157 |
158 |
159 |
160 |
161 |
162 |
163 |
164 |
165 |
166 |
--------------------------------------------------------------------------------
/docs/pkgdown.css:
--------------------------------------------------------------------------------
1 | /* Sticky footer */
2 |
3 | /**
4 | * Basic idea: https://philipwalton.github.io/solved-by-flexbox/demos/sticky-footer/
5 | * Details: https://github.com/philipwalton/solved-by-flexbox/blob/master/assets/css/components/site.css
6 | *
7 | * .Site -> body > .container
8 | * .Site-content -> body > .container .row
9 | * .footer -> footer
10 | *
11 | * Key idea seems to be to ensure that .container and __all its parents__
12 | * have height set to 100%
13 | *
14 | */
15 |
16 | html, body {
17 | height: 100%;
18 | }
19 |
20 | body {
21 | position: relative;
22 | }
23 |
24 | body > .container {
25 | display: flex;
26 | height: 100%;
27 | flex-direction: column;
28 | }
29 |
30 | body > .container .row {
31 | flex: 1 0 auto;
32 | }
33 |
34 | footer {
35 | margin-top: 45px;
36 | padding: 35px 0 36px;
37 | border-top: 1px solid #e5e5e5;
38 | color: #666;
39 | display: flex;
40 | flex-shrink: 0;
41 | }
42 | footer p {
43 | margin-bottom: 0;
44 | }
45 | footer div {
46 | flex: 1;
47 | }
48 | footer .pkgdown {
49 | text-align: right;
50 | }
51 | footer p {
52 | margin-bottom: 0;
53 | }
54 |
55 | img.icon {
56 | float: right;
57 | }
58 |
59 | img {
60 | max-width: 100%;
61 | }
62 |
63 | /* Fix bug in bootstrap (only seen in firefox) */
64 | summary {
65 | display: list-item;
66 | }
67 |
68 | /* Typographic tweaking ---------------------------------*/
69 |
70 | .contents .page-header {
71 | margin-top: calc(-60px + 1em);
72 | }
73 |
74 | dd {
75 | margin-left: 3em;
76 | }
77 |
78 | /* Section anchors ---------------------------------*/
79 |
80 | a.anchor {
81 | margin-left: -30px;
82 | display:inline-block;
83 | width: 30px;
84 | height: 30px;
85 | visibility: hidden;
86 |
87 | background-image: url(./link.svg);
88 | background-repeat: no-repeat;
89 | background-size: 20px 20px;
90 | background-position: center center;
91 | }
92 |
93 | .hasAnchor:hover a.anchor {
94 | visibility: visible;
95 | }
96 |
97 | @media (max-width: 767px) {
98 | .hasAnchor:hover a.anchor {
99 | visibility: hidden;
100 | }
101 | }
102 |
103 |
104 | /* Fixes for fixed navbar --------------------------*/
105 |
106 | .contents h1, .contents h2, .contents h3, .contents h4 {
107 | padding-top: 60px;
108 | margin-top: -40px;
109 | }
110 |
111 | /* Navbar submenu --------------------------*/
112 |
113 | .dropdown-submenu {
114 | position: relative;
115 | }
116 |
117 | .dropdown-submenu>.dropdown-menu {
118 | top: 0;
119 | left: 100%;
120 | margin-top: -6px;
121 | margin-left: -1px;
122 | border-radius: 0 6px 6px 6px;
123 | }
124 |
125 | .dropdown-submenu:hover>.dropdown-menu {
126 | display: block;
127 | }
128 |
129 | .dropdown-submenu>a:after {
130 | display: block;
131 | content: " ";
132 | float: right;
133 | width: 0;
134 | height: 0;
135 | border-color: transparent;
136 | border-style: solid;
137 | border-width: 5px 0 5px 5px;
138 | border-left-color: #cccccc;
139 | margin-top: 5px;
140 | margin-right: -10px;
141 | }
142 |
143 | .dropdown-submenu:hover>a:after {
144 | border-left-color: #ffffff;
145 | }
146 |
147 | .dropdown-submenu.pull-left {
148 | float: none;
149 | }
150 |
151 | .dropdown-submenu.pull-left>.dropdown-menu {
152 | left: -100%;
153 | margin-left: 10px;
154 | border-radius: 6px 0 6px 6px;
155 | }
156 |
157 | /* Sidebar --------------------------*/
158 |
159 | #pkgdown-sidebar {
160 | margin-top: 30px;
161 | position: -webkit-sticky;
162 | position: sticky;
163 | top: 70px;
164 | }
165 |
166 | #pkgdown-sidebar h2 {
167 | font-size: 1.5em;
168 | margin-top: 1em;
169 | }
170 |
171 | #pkgdown-sidebar h2:first-child {
172 | margin-top: 0;
173 | }
174 |
175 | #pkgdown-sidebar .list-unstyled li {
176 | margin-bottom: 0.5em;
177 | }
178 |
179 | /* bootstrap-toc tweaks ------------------------------------------------------*/
180 |
181 | /* All levels of nav */
182 |
183 | nav[data-toggle='toc'] .nav > li > a {
184 | padding: 4px 20px 4px 6px;
185 | font-size: 1.5rem;
186 | font-weight: 400;
187 | color: inherit;
188 | }
189 |
190 | nav[data-toggle='toc'] .nav > li > a:hover,
191 | nav[data-toggle='toc'] .nav > li > a:focus {
192 | padding-left: 5px;
193 | color: inherit;
194 | border-left: 1px solid #878787;
195 | }
196 |
197 | nav[data-toggle='toc'] .nav > .active > a,
198 | nav[data-toggle='toc'] .nav > .active:hover > a,
199 | nav[data-toggle='toc'] .nav > .active:focus > a {
200 | padding-left: 5px;
201 | font-size: 1.5rem;
202 | font-weight: 400;
203 | color: inherit;
204 | border-left: 2px solid #878787;
205 | }
206 |
207 | /* Nav: second level (shown on .active) */
208 |
209 | nav[data-toggle='toc'] .nav .nav {
210 | display: none; /* Hide by default, but at >768px, show it */
211 | padding-bottom: 10px;
212 | }
213 |
214 | nav[data-toggle='toc'] .nav .nav > li > a {
215 | padding-left: 16px;
216 | font-size: 1.35rem;
217 | }
218 |
219 | nav[data-toggle='toc'] .nav .nav > li > a:hover,
220 | nav[data-toggle='toc'] .nav .nav > li > a:focus {
221 | padding-left: 15px;
222 | }
223 |
224 | nav[data-toggle='toc'] .nav .nav > .active > a,
225 | nav[data-toggle='toc'] .nav .nav > .active:hover > a,
226 | nav[data-toggle='toc'] .nav .nav > .active:focus > a {
227 | padding-left: 15px;
228 | font-weight: 500;
229 | font-size: 1.35rem;
230 | }
231 |
232 | /* orcid ------------------------------------------------------------------- */
233 |
234 | .orcid {
235 | font-size: 16px;
236 | color: #A6CE39;
237 | /* margins are required by official ORCID trademark and display guidelines */
238 | margin-left:4px;
239 | margin-right:4px;
240 | vertical-align: middle;
241 | }
242 |
243 | /* Reference index & topics ----------------------------------------------- */
244 |
245 | .ref-index th {font-weight: normal;}
246 |
247 | .ref-index td {vertical-align: top;}
248 | .ref-index .icon {width: 40px;}
249 | .ref-index .alias {width: 40%;}
250 | .ref-index-icons .alias {width: calc(40% - 40px);}
251 | .ref-index .title {width: 60%;}
252 |
253 | .ref-arguments th {text-align: right; padding-right: 10px;}
254 | .ref-arguments th, .ref-arguments td {vertical-align: top;}
255 | .ref-arguments .name {width: 20%;}
256 | .ref-arguments .desc {width: 80%;}
257 |
258 | /* Nice scrolling for wide elements --------------------------------------- */
259 |
260 | table {
261 | display: block;
262 | overflow: auto;
263 | }
264 |
265 | /* Syntax highlighting ---------------------------------------------------- */
266 |
267 | pre {
268 | word-wrap: normal;
269 | word-break: normal;
270 | border: 1px solid #eee;
271 | }
272 |
273 | pre, code {
274 | background-color: #f8f8f8;
275 | color: #333;
276 | }
277 |
278 | pre code {
279 | overflow: auto;
280 | word-wrap: normal;
281 | white-space: pre;
282 | }
283 |
284 | pre .img {
285 | margin: 5px 0;
286 | }
287 |
288 | pre .img img {
289 | background-color: #fff;
290 | display: block;
291 | height: auto;
292 | }
293 |
294 | code a, pre a {
295 | color: #375f84;
296 | }
297 |
298 | a.sourceLine:hover {
299 | text-decoration: none;
300 | }
301 |
302 | .fl {color: #1514b5;}
303 | .fu {color: #000000;} /* function */
304 | .ch,.st {color: #036a07;} /* string */
305 | .kw {color: #264D66;} /* keyword */
306 | .co {color: #888888;} /* comment */
307 |
308 | .message { color: black; font-weight: bolder;}
309 | .error { color: orange; font-weight: bolder;}
310 | .warning { color: #6A0366; font-weight: bolder;}
311 |
312 | /* Clipboard --------------------------*/
313 |
314 | .hasCopyButton {
315 | position: relative;
316 | }
317 |
318 | .btn-copy-ex {
319 | position: absolute;
320 | right: 0;
321 | top: 0;
322 | visibility: hidden;
323 | }
324 |
325 | .hasCopyButton:hover button.btn-copy-ex {
326 | visibility: visible;
327 | }
328 |
329 | /* headroom.js ------------------------ */
330 |
331 | .headroom {
332 | will-change: transform;
333 | transition: transform 200ms linear;
334 | }
335 | .headroom--pinned {
336 | transform: translateY(0%);
337 | }
338 | .headroom--unpinned {
339 | transform: translateY(-100%);
340 | }
341 |
342 | /* mark.js ----------------------------*/
343 |
344 | mark {
345 | background-color: rgba(255, 255, 51, 0.5);
346 | border-bottom: 2px solid rgba(255, 153, 51, 0.3);
347 | padding: 1px;
348 | }
349 |
350 | /* vertical spacing after htmlwidgets */
351 | .html-widget {
352 | margin-bottom: 10px;
353 | }
354 |
355 | /* fontawesome ------------------------ */
356 |
357 | .fab {
358 | font-family: "Font Awesome 5 Brands" !important;
359 | }
360 |
361 | /* don't display links in code chunks when printing */
362 | /* source: https://stackoverflow.com/a/10781533 */
363 | @media print {
364 | code a:link:after, code a:visited:after {
365 | content: "";
366 | }
367 | }
368 |
--------------------------------------------------------------------------------
/docs/index.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 | Adds tags to ggpot2 facets • tagger
9 |
10 |
11 |
12 |
13 |
14 |
15 |
16 |
20 |
21 |
22 |
23 |
61 |
62 |
63 |
65 |
66 |
67 |
The goal of tagger is to easily add tags to facetted plots in order to identify panles.
68 |
69 |
70 | Installation
71 |
72 |
73 |
74 |
75 |
You can install the development version from GitHub with:
76 |
# install.packages("devtools")
77 | devtools :: install_github ("eliocamp/tagger" )
78 |
79 |
80 |
81 | Example
82 |
In the default usage, you can simply add tag_facets() to add a tag to each panel of a ggplo2 plot.
83 |
90 |
If you want to tag rows and columns instead of each panel indivdually, you can set it with the tag argument.
91 |
95 |
96 |
97 |
98 |
99 |
100 |
115 |
116 |
117 |
118 |
127 |
128 |
129 |
130 |
131 |
132 |
133 |
134 |
--------------------------------------------------------------------------------
/docs/docsearch.css:
--------------------------------------------------------------------------------
1 | /* Docsearch -------------------------------------------------------------- */
2 | /*
3 | Source: https://github.com/algolia/docsearch/
4 | License: MIT
5 | */
6 |
7 | .algolia-autocomplete {
8 | display: block;
9 | -webkit-box-flex: 1;
10 | -ms-flex: 1;
11 | flex: 1
12 | }
13 |
14 | .algolia-autocomplete .ds-dropdown-menu {
15 | width: 100%;
16 | min-width: none;
17 | max-width: none;
18 | padding: .75rem 0;
19 | background-color: #fff;
20 | background-clip: padding-box;
21 | border: 1px solid rgba(0, 0, 0, .1);
22 | box-shadow: 0 .5rem 1rem rgba(0, 0, 0, .175);
23 | }
24 |
25 | @media (min-width:768px) {
26 | .algolia-autocomplete .ds-dropdown-menu {
27 | width: 175%
28 | }
29 | }
30 |
31 | .algolia-autocomplete .ds-dropdown-menu::before {
32 | display: none
33 | }
34 |
35 | .algolia-autocomplete .ds-dropdown-menu [class^=ds-dataset-] {
36 | padding: 0;
37 | background-color: rgb(255,255,255);
38 | border: 0;
39 | max-height: 80vh;
40 | }
41 |
42 | .algolia-autocomplete .ds-dropdown-menu .ds-suggestions {
43 | margin-top: 0
44 | }
45 |
46 | .algolia-autocomplete .algolia-docsearch-suggestion {
47 | padding: 0;
48 | overflow: visible
49 | }
50 |
51 | .algolia-autocomplete .algolia-docsearch-suggestion--category-header {
52 | padding: .125rem 1rem;
53 | margin-top: 0;
54 | font-size: 1.3em;
55 | font-weight: 500;
56 | color: #00008B;
57 | border-bottom: 0
58 | }
59 |
60 | .algolia-autocomplete .algolia-docsearch-suggestion--wrapper {
61 | float: none;
62 | padding-top: 0
63 | }
64 |
65 | .algolia-autocomplete .algolia-docsearch-suggestion--subcategory-column {
66 | float: none;
67 | width: auto;
68 | padding: 0;
69 | text-align: left
70 | }
71 |
72 | .algolia-autocomplete .algolia-docsearch-suggestion--content {
73 | float: none;
74 | width: auto;
75 | padding: 0
76 | }
77 |
78 | .algolia-autocomplete .algolia-docsearch-suggestion--content::before {
79 | display: none
80 | }
81 |
82 | .algolia-autocomplete .ds-suggestion:not(:first-child) .algolia-docsearch-suggestion--category-header {
83 | padding-top: .75rem;
84 | margin-top: .75rem;
85 | border-top: 1px solid rgba(0, 0, 0, .1)
86 | }
87 |
88 | .algolia-autocomplete .ds-suggestion .algolia-docsearch-suggestion--subcategory-column {
89 | display: block;
90 | padding: .1rem 1rem;
91 | margin-bottom: 0.1;
92 | font-size: 1.0em;
93 | font-weight: 400
94 | /* display: none */
95 | }
96 |
97 | .algolia-autocomplete .algolia-docsearch-suggestion--title {
98 | display: block;
99 | padding: .25rem 1rem;
100 | margin-bottom: 0;
101 | font-size: 0.9em;
102 | font-weight: 400
103 | }
104 |
105 | .algolia-autocomplete .algolia-docsearch-suggestion--text {
106 | padding: 0 1rem .5rem;
107 | margin-top: -.25rem;
108 | font-size: 0.8em;
109 | font-weight: 400;
110 | line-height: 1.25
111 | }
112 |
113 | .algolia-autocomplete .algolia-docsearch-footer {
114 | width: 110px;
115 | height: 20px;
116 | z-index: 3;
117 | margin-top: 10.66667px;
118 | float: right;
119 | font-size: 0;
120 | line-height: 0;
121 | }
122 |
123 | .algolia-autocomplete .algolia-docsearch-footer--logo {
124 | background-image: url("data:image/svg+xml;utf8, ");
125 | background-repeat: no-repeat;
126 | background-position: 50%;
127 | background-size: 100%;
128 | overflow: hidden;
129 | text-indent: -9000px;
130 | width: 100%;
131 | height: 100%;
132 | display: block;
133 | transform: translate(-8px);
134 | }
135 |
136 | .algolia-autocomplete .algolia-docsearch-suggestion--highlight {
137 | color: #FF8C00;
138 | background: rgba(232, 189, 54, 0.1)
139 | }
140 |
141 |
142 | .algolia-autocomplete .algolia-docsearch-suggestion--text .algolia-docsearch-suggestion--highlight {
143 | box-shadow: inset 0 -2px 0 0 rgba(105, 105, 105, .5)
144 | }
145 |
146 | .algolia-autocomplete .ds-suggestion.ds-cursor .algolia-docsearch-suggestion--content {
147 | background-color: rgba(192, 192, 192, .15)
148 | }
149 |
--------------------------------------------------------------------------------
/R/tag-facet.R:
--------------------------------------------------------------------------------
1 | #' Adds tags to facets
2 | #'
3 | #' @param tag Character indicating the element to tag. Possible values are
4 | #' * "panel": each single panels is individually tag.
5 | #' * "rc": facets are tagged by row and then column.
6 | #' * "cr": factes are tagged by columns and then row.
7 | #'
8 | #' @param position Character indicating the position of the tag. Options are "tl"
9 | #' (top-left), "tr" (top-right), "br" (bottom-right) and "bl" (bottom-left).
10 | #' Alternatively, for finer control, it can be a list of elements "x", "u",
11 | #' "hjust" and "vjust" that define the position of the tag within each panel.
12 | #'
13 | #' @inheritParams patchwork::plot_annotation
14 | #'
15 | #' @param tag_pool An optional character vector of user-defined "pool" of tags.
16 | #' If not `NULL`, it will be used instead of `tag_levels`. Should be at least
17 | #' as long as the total number of panels.
18 | #'
19 | #'
20 | #' @details
21 | #'
22 | #' Tags inherit aesthetic properties (size, font, colour, etc...) from strip.text and
23 | #' strip.background defined by [ggplot2::theme()]. For fine-grained detail, these can be
24 | #' overriden by setting tagger.panel.tag.text and tagger.panel.tag.background.
25 | #'
26 | #' @examples
27 | #'
28 | #' library(ggplot2)
29 | #' # Base plot
30 | #' g <- ggplot(mtcars, aes(hp, mpg)) +
31 | #' geom_point() +
32 | #' facet_grid(cyl ~ vs)
33 | #'
34 | #' g + tag_facets()
35 | #' g + tag_facets("rc")
36 | #' g + tag_facets("cr")
37 | #' g + tag_facets(position = "br")
38 | #' g + tag_facets("rc", tag_levels = c("A", "I"))
39 | #'
40 | #' # You can get finer control over position.
41 | #' g + tag_facets(position = list(x = 0.5, y = 0.5))
42 | #'
43 | #' g + tag_facets(tag_pool = c("one", "two", "three", "four", "five", "six"), tag_suffix = "")
44 | #' # Thanks to theme inheritance, tags should look aceptable
45 | #' # out of the box in any theme.
46 | #' g + tag_facets() +
47 | #' theme_dark()
48 | #'
49 | #' # But you can control their appearance and create your own atrocities
50 | #' g + tag_facets() +
51 | #' theme_dark() +
52 | #' theme(tagger.panel.tag.text = element_text(color = "red", size = 16),
53 | #' tagger.panel.tag.background = element_rect(fill = "purple"))
54 | #'
55 | #' @export
56 | #' @import checkmate
57 | tag_facets <- function(tag = c("panel", "rc", "cr"), position = "tl",
58 | tag_levels = c("a", "1"), tag_pool = NULL, tag_prefix = "",
59 | tag_suffix = ")", tag_sep = ".") {
60 |
61 | if (!is.list(position)) {
62 | assert_choice(position, c("tl", "tr", "bl", "br"))
63 |
64 | position <- switch(position,
65 | tl = list(x = 0, y = 1, hjust = 0, vjust = 1),
66 | tr = list(x = 1, y = 1, hjust = 1, vjust = 1),
67 | bl = list(x = 0, y = 0, hjust = 0, vjust = 0),
68 | br = list(x = 1, y = 0, hjust = 1, vjust = 0),
69 | position)
70 | }
71 |
72 | position$hjust <- if (!is.null(position$hjust)) position$hjust else 0.5
73 | position$vjust <- if (!is.null(position$vjust)) position$vjust else 0.5
74 |
75 | checks <- makeAssertCollection()
76 |
77 |
78 | assert_list(position, types = "numeric", len = 4, add = checks)
79 | assert_names(names(position), must.include = c("x", "y", "hjust", "vjust"),
80 | .var.name = "position", add = checks)
81 |
82 | assert_choice(tag[1], c("panel", "rc", "cr"), add = checks)
83 | assert_character(tag_prefix, any.missing = FALSE, len = 1, add = checks)
84 | assert_character(tag_suffix, any.missing = FALSE, len = 1, add = checks)
85 | assert_character(tag_sep, any.missing = FALSE, len = 1, add = checks)
86 |
87 | tag <- switch(tag[1],
88 | rc = c("ROW", "COL"),
89 | cr = c("COL", "ROW"),
90 | panel = "PANEL")
91 |
92 | assert_character(tag_levels, any.missing = FALSE, min.len = length(tag), add = checks)
93 | reportAssertions(checks)
94 |
95 |
96 | structure(list(tag = tag, tag_pool = tag_pool, tag_levels = tag_levels, open = tag_prefix,
97 | close = tag_suffix, tag_sep = tag_sep, position = position),
98 | class = "tagger")
99 | }
100 |
101 | #' @export
102 | #' @importFrom ggplot2 ggplot_add
103 | ggplot_add.tagger <- function(object, plot, object_name) {
104 | class(plot) <- c("ggtagged", class(plot))
105 | plot$tag_options <- object
106 | plot
107 | }
108 |
109 | `%||%` <- function(a, b) {
110 | if (length(a) == 0) return(a)
111 | nulls <- lengths(a) == 0
112 | if (all(nulls[-length(nulls)])) return(b)
113 | a[nulls] <- b[nulls]
114 | a
115 | }
116 |
117 | as.element_text <- function(x) {
118 | if (length(x) == 0) return(ggplot2::element_text())
119 | return(x)
120 | }
121 |
122 |
123 | as.element_rect <- function(x) {
124 | if (length(x) == 0) return(ggplot2::element_rect())
125 | return(x)
126 | }
127 |
128 |
129 | #' @export
130 | #' @importFrom ggplot2 ggplot_build
131 | ggplot_build.ggtagged <- function(plot) {
132 | gb <- NextMethod("ggplot_build")
133 | gb <- add_class(gb, "ggplot_build_ggtagged")
134 | gb
135 | }
136 |
137 | add_class <- function(object, class) {
138 | class(object) <- c(class, setdiff(class(object), class))
139 | return(object)
140 | }
141 |
142 |
143 | #' @export
144 | #' @importFrom ggplot2 ggplot_gtable
145 | ggplot_gtable.ggplot_build_ggtagged <- function(data) {
146 | gt <- NextMethod("ggplot_gtable")
147 | lay <- assign_tags(data)
148 | facet_tags <- lay$TAG_PANEL
149 |
150 | tag_options <- data$plot$tag_options
151 |
152 | facet_tags <- paste0(tag_options$open, facet_tags, tag_options$close)
153 |
154 | theme <- ggplot2:::plot_theme(data$plot)
155 |
156 | tag_style <- ggplot2::calc_element("tagger.panel.tag.text", theme, verbose = FALSE, skip_blank = FALSE)
157 | tag_gpar <- list(col = tag_style$colour,
158 | family = tag_style$family,
159 | fontface = tag_style$face,
160 | fontsize = tag_style$size,
161 | lineheight = tag_style$lineheight)
162 | tag_gpar <- tag_gpar[lengths(tag_gpar) != 0]
163 | tag_gpar <- do.call(grid::gpar, tag_gpar)
164 |
165 | box <- ggplot2::calc_element("tagger.panel.tag.background", theme, verbose = FALSE, skip_blank = FALSE)
166 | box_gp <- grid::gpar(col = box$colour, fill = box$fill, lty = box$linetype, lwd = box$size)
167 |
168 | x <- tag_options$position$x
169 | y <- tag_options$position$y
170 |
171 | hjust <- tag_options$position$hjust
172 | vjust <- tag_options$position$vjust
173 |
174 | panels <- which(startsWith(gt$layout$name, "panel"))
175 |
176 | # Panels are sorted top to bottom, left to right
177 | panels <- c(matrix(panels, ncol = max(lay$ROW), nrow = max(lay$COL), byrow = TRUE))
178 |
179 | # Remove empty panels
180 | empty <- vapply(panels, function(p) inherits(gt$grobs[p][[1]], "zeroGrob"),
181 | FUN.VALUE = logical(1))
182 | panels <- panels[!empty]
183 |
184 | grob_args <- list(x = x, y = y, hjust = hjust, vjust = vjust,
185 | rot = tag_style$angle,
186 | gp = tag_gpar,
187 | box_gp = box_gp,
188 | # r = grid::unit(c(0.1, .1, .1, .1), "lines"),
189 | padding = grid::unit(c(0.2, .2, .2, .2), "lines"),
190 | use_markdown = FALSE)
191 | grob_args <- grob_args[lengths(grob_args) != 0]
192 | grob <- gridtext::richtext_grob
193 |
194 | for (p in seq_along(facet_tags)) {
195 | grob_args$text <- facet_tags[p]
196 | tagGrob <- do.call(grob, grob_args)
197 | this_panel <- gt$layout[panels[p], ]
198 | gt <- gtable::gtable_add_grob(gt, tagGrob, t = this_panel$t, l = this_panel$l, clip = "on", z = 2)
199 | }
200 |
201 | return(gt)
202 | }
203 |
204 |
205 | assign_tags <- function(plot) {
206 | tag_options <- plot$plot$tag_options
207 |
208 | lay <- plot$layout$layout
209 | o <- order(lay$ROW, lay$COL)
210 | lay <- lay[o, ]
211 | facet_vars <- lay[toupper(tag_options$tag)]
212 | facet_vars <- lapply(facet_vars, function(x) as.numeric(as.factor(x)))
213 | tag_options$tag_levels <- rep_len(tag_options$tag_levels, length.out = length(facet_vars))
214 | facet_tags <- lapply(seq_along(facet_vars), function(i) {
215 | i_panels <- facet_vars[[i]]
216 | if (is.null(tag_options$tag_pool[[i]])) {
217 | tag_pool <- switch(tag_options$tag_levels[i],
218 | a = letters[i_panels],
219 | A = LETTERS[i_panels],
220 | "1" = i_panels,
221 | "i" = tolower(utils::as.roman(i_panels)),
222 | "I" = utils::as.roman(i_panels),
223 | stop("tag_levels is not valid")
224 | )
225 |
226 | } else {
227 | tag_pool <- tag_options$tag_pool[i_panels]
228 | }
229 | return(tag_pool)
230 | })
231 |
232 | if (!identical(tag_options$tag, "PANEL")) {
233 | lay[paste0("TAG_", tag_options$tag)] <- facet_tags
234 | }
235 |
236 | facet_tags <- Reduce(function(a, b) paste(a, b, sep = tag_options$tag_sep), facet_tags)
237 |
238 | lay[["TAG_PANEL"]] <- facet_tags
239 |
240 | lay[order(o), ]
241 | return(lay)
242 | }
243 |
244 | #' Get labels asigned to each panel of a tagged plot
245 | #'
246 | #' @param filter an expression that, evaluated within the data used
247 | #' to generate the facets of the plot, evaluates to a logical vector
248 | #' or a sequence of rows.
249 | #' @param plot a plot object
250 | #' @param n number of expected panels.
251 | #'
252 | #' @return
253 | #' `get_tags()`, `get_row()` and `get_col()` return a character vector
254 | #' of length `n` with the tags, unique rows or unique columns that meet
255 | #' the `filter` condition.
256 | #'
257 | #' `get_layout()` returns the full data.frame describing the panel layout.
258 | #'
259 | #'
260 | #' @examples
261 | #' library(ggplot2)
262 | #' g <- ggplot(mtcars, aes(hp, mpg)) +
263 | #' geom_point() +
264 | #' facet_grid(cyl ~ vs) +
265 | #' tag_facets("rc")
266 | #'
267 | #' # By default these functions retrieve tags from
268 | #' # the result of ggplo2::last_plot().
269 | #'
270 | #' # Get all tags
271 | #' get_layout()
272 | #'
273 | #' # Get one tag
274 | #' get_tag(cyl == 4 & vs == 0)
275 | #'
276 | #' # Get more than one tag
277 | #' get_tag(cyl == 4, n = 2)
278 | #'
279 | #'
280 | #' get_row(cyl == 4)
281 | #' get_col(vs == 0)
282 | #'
283 | #' # Use it with inline markdown to refer always to the correct panel:
284 | #' # "As you can see in panel `r get_tag(cyl == 4 & vs == 0)` ..."
285 | #'
286 | #' @export
287 | get_layout <- function(plot = ggplot2::last_plot()) {
288 | if (!inherits(plot, "ggtagged")) {
289 | stop("The plot has no tags.")
290 | }
291 | plot <- ggplot_build_memoised(plot)
292 | lay <- assign_tags(plot)
293 | lay <- lay[, setdiff(colnames(lay), c("SCALE_X", "SCALE_Y"))]
294 |
295 | return(lay)
296 | }
297 |
298 | #' @export
299 | #' @rdname get_layout
300 | get_tag <- function(filter = TRUE, plot = ggplot2::last_plot(), n = 1) {
301 | lay <- get_layout(plot = plot)
302 | filter <- eval(substitute(filter), envir = lay)
303 | lay <- lay[filter, ]
304 |
305 | if (nrow(lay) != n) {
306 | stop("Returned ", nrow(lay), ifelse(n == 1, " panel", " panels"),
307 | " (expected ", n, ").")
308 | }
309 | lay$TAG_PANEL
310 | }
311 |
312 | if (requireNamespace("memoise", quietly = TRUE)) {
313 | ggplot_build_memoised <- memoise::memoise(ggplot2::ggplot_build)
314 | } else {
315 | ggplot_build_memoised <- ggplot2::ggplot_build
316 | }
317 |
318 | #' @export
319 | #' @rdname get_layout
320 | get_row <- function(filter = TRUE, plot = ggplot2::last_plot(), n = 1) {
321 | lay <- get_layout(plot = plot)
322 | filter <- eval(substitute(filter), envir = lay)
323 | lay <- lay[filter, ]
324 |
325 | row <- unique(lay$TAG_ROW)
326 | if (length(row) != n) {
327 | stop("Returned ", length(row), ifelse(n == 1, " panel", " panels"),
328 | " (expected ", n, ").")
329 | }
330 | row
331 | }
332 |
333 | #' @export
334 | #' @rdname get_layout
335 | get_col <- function(filter = TRUE, plot = ggplot2::last_plot(), n = 1) {
336 | lay <- get_layout(plot = plot)
337 | filter <- eval(substitute(filter), envir = lay)
338 | lay <- lay[filter, ]
339 |
340 | col <- unique(lay$TAG_COL)
341 | if (length(col) != n) {
342 | stop("Returned ", length(col), ifelse(n == 1, " panel", " panels"),
343 | " (expected ", n, ").")
344 | }
345 | col
346 | }
347 |
--------------------------------------------------------------------------------
/docs/reference/tag_facets.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 | Adds tags to facets — tag_facets • tagger
10 |
11 |
12 |
13 |
14 |
15 |
16 |
17 |
18 |
19 |
20 |
21 |
22 |
23 |
24 |
25 |
26 |
27 |
28 |
29 |
30 |
31 |
32 |
33 |
34 |
35 |
36 |
37 |
38 |
39 |
40 |
41 |
42 |
43 |
44 |
45 |
46 |
47 |
48 |
49 |
50 |
51 |
52 |
56 |
57 |
58 |
59 |
60 |
61 |
62 |
63 |
64 |
98 |
99 |
100 |
101 |
102 |
103 |
104 |
105 |
110 |
111 |
112 |
Adds tags to facets
113 |
114 |
115 |
tag_facets (
116 | tag = c ("panel" , "rc" , "cr" ),
117 | position = "tl" ,
118 | tag_levels = c ("a" , "1" ),
119 | tag_pool = NULL ,
120 | tag_prefix = "" ,
121 | tag_suffix = ")" ,
122 | tag_sep = "."
123 | )
124 |
125 |
Arguments
126 |
127 |
128 |
129 | tag
130 | Character indicating the element to tag. Possible values are
131 | "panel": each single panels is individually tag.
132 | "rc": facets are tagged by row and then column.
133 | "cr": factes are tagged by columns and then row.
134 |
135 |
136 |
137 | position
138 | Character indicating the position of the tag. Options are "tl"
139 | (top-left), "tr" (top-right), "br" (bottom-right) and "bl" (bottom-left).
140 | Alternatively, for finer control, it can be a list of elements "x", "u",
141 | "hjust" and "vjust" that define the position of the tag within each panel.
142 |
143 |
144 | tag_levels
145 | A character vector defining the enumeration format to use
146 | at each level. Possible values are 'a' for lowercase letters, 'A' for
147 | uppercase letters, '1' for numbers, 'i' for lowercase Roman numerals, and
148 | 'I' for uppercase Roman numerals.
149 |
150 |
151 | tag_pool
152 | An optional character vector of user-defined "pool" of tags.
153 | If not NULL, it will be used instead of tag_levels. Should be at least
154 | as long as the total number of panels.
155 |
156 |
157 | tag_prefix
158 | Strings that should appear before or after the
159 | tag.
160 |
161 |
162 | tag_suffix
163 | Strings that should appear before or after the
164 | tag.
165 |
166 |
167 | tag_sep
168 | A separator between different tag levels
169 |
170 |
171 |
172 |
Details
173 |
174 |
Tags inherit aesthetic properties (size, font, colour, etc...) from strip.text and
175 | strip.background defined by ggplot2::theme() . For fine-grained detail, these can be
176 | overriden by setting tagger.panel.tag.text and tagger.panel.tag.background.
177 |
178 |
Examples
179 |
g + tag_facets ("rc" )
g + tag_facets (position = "br" )
198 |
199 |
200 |
205 |
206 |
207 |
208 |
218 |
219 |
220 |
221 |
222 |
223 |
224 |
225 |
226 |
227 |
--------------------------------------------------------------------------------