├── .Rbuildignore ├── .codecov.yml ├── .gitignore ├── .travis.yml ├── CONDUCT.md ├── DESCRIPTION ├── LICENSE ├── LICENSE.md ├── NAMESPACE ├── NEWS.md ├── R ├── geom-econodist.R ├── ggeconodist-package.R ├── globals.R ├── legend-helpers.R ├── stat-econodist.R ├── theme-econ.R ├── utils-infix-helpers.R ├── utils-pipe.R └── utils.R ├── README.Rmd ├── README.md ├── ggeconodist.Rproj ├── inst └── tinytest │ └── test_ggeconodist.R ├── man ├── add_econodist_legend.Rd ├── econodist_legend_grob.Rd ├── figures │ ├── README-gm-1.png │ ├── README-mam-1.png │ ├── README-mpg-1.png │ ├── README-mpg-2.png │ └── README-mpg-3.png ├── geom_econodist.Rd ├── ggeconodist.Rd ├── left_align.Rd ├── mammogram_costs.Rd ├── pipe.Rd └── theme_econodist.Rd └── tests └── tinytest.R /.Rbuildignore: -------------------------------------------------------------------------------- 1 | ^.vscode$ 2 | ^.*\.Rproj$ 3 | ^\.Rproj\.user$ 4 | ^\.travis\.yml$ 5 | ^README\.*Rmd$ 6 | ^README\.*html$ 7 | ^NOTES\.*Rmd$ 8 | ^NOTES\.*html$ 9 | ^\.codecov\.yml$ 10 | ^README_files$ 11 | ^doc$ 12 | ^docs$ 13 | ^tmp$ 14 | ^notes$ 15 | ^CONDUCT.*$ 16 | ^CODE.*$ 17 | ^\.gitlab-ci\.yml$ 18 | ^LICENSE\.md$ 19 | -------------------------------------------------------------------------------- /.codecov.yml: -------------------------------------------------------------------------------- 1 | comment: false 2 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | .DS_Store 2 | .Rproj.user 3 | .Rhistory 4 | .RData 5 | .Rproj 6 | README_cache 7 | src/*.o 8 | src/*.so 9 | src/*.dll 10 | -------------------------------------------------------------------------------- /.travis.yml: -------------------------------------------------------------------------------- 1 | language: R 2 | sudo: false 3 | cache: packages 4 | 5 | after_success: 6 | - Rscript -e 'covr::codecov()' 7 | -------------------------------------------------------------------------------- /CONDUCT.md: -------------------------------------------------------------------------------- 1 | # Contributor Code of Conduct 2 | 3 | As contributors and maintainers of this project, we pledge to respect all people who 4 | contribute through reporting issues, posting feature requests, updating documentation, 5 | submitting pull requests or patches, and other activities. 6 | 7 | We are committed to making participation in this project a harassment-free experience for 8 | everyone, regardless of level of experience, gender, gender identity and expression, 9 | sexual orientation, disability, personal appearance, body size, race, ethnicity, age, or religion. 10 | 11 | Examples of unacceptable behavior by participants include the use of sexual language or 12 | imagery, derogatory comments or personal attacks, trolling, public or private harassment, 13 | insults, or other unprofessional conduct. 14 | 15 | Project maintainers have the right and responsibility to remove, edit, or reject comments, 16 | commits, code, wiki edits, issues, and other contributions that are not aligned to this 17 | Code of Conduct. Project maintainers who do not follow the Code of Conduct may be removed 18 | from the project team. 19 | 20 | Instances of abusive, harassing, or otherwise unacceptable behavior may be reported by 21 | opening an issue or contacting one or more of the project maintainers. 22 | 23 | This Code of Conduct is adapted from the Contributor Covenant 24 | (http:contributor-covenant.org), version 1.0.0, available at 25 | http://contributor-covenant.org/version/1/0/0/ 26 | -------------------------------------------------------------------------------- /DESCRIPTION: -------------------------------------------------------------------------------- 1 | Package: ggeconodist 2 | Type: Package 3 | Title: Create Diminutive Distribution Charts 4 | Version: 0.1.0 5 | Date: 2019-07-14 6 | Authors@R: c( person("Bob", "Rudis", email = "bob@rud.is", role = 7 | c("aut", "cre"), comment = c(ORCID = "0000-0001-5670-2640")) ) 8 | Maintainer: Bob Rudis 9 | Description: 'The Economist' has a unique boxplot aesthetic for 10 | communicating distrribution characteristics. Tools are provided 11 | to create similar charts in 'ggplot2'. 12 | URL: https://gitlab.com/hrbrmstr/ggeconodist 13 | BugReports: https://gitlab.com/hrbrmstr/ggeconodist/issues 14 | Encoding: UTF-8 15 | License: MIT + file LICENSE 16 | Suggests: covr, tinytest, scales 17 | Depends: R (>= 3.2.0), ggplot2 (>= 3.2.0), grid 18 | Imports: 19 | gtable, 20 | magrittr 21 | Roxygen: list(markdown = TRUE) 22 | RoxygenNote: 6.1.1 23 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | YEAR: 2019 2 | COPYRIGHT HOLDER: Bob Rudis 3 | -------------------------------------------------------------------------------- /LICENSE.md: -------------------------------------------------------------------------------- 1 | # MIT License 2 | 3 | Copyright (c) 2019 Bob Rudis 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. 22 | -------------------------------------------------------------------------------- /NAMESPACE: -------------------------------------------------------------------------------- 1 | # Generated by roxygen2: do not edit by hand 2 | 3 | export("%>%") 4 | export(GeomEconodist) 5 | export(StatEconodist) 6 | export(add_econodist_legend) 7 | export(econodist_legend_grob) 8 | export(geom_econodist) 9 | export(left_align) 10 | export(mammogram_costs) 11 | export(stat_econodist) 12 | export(theme_econodist) 13 | import(ggplot2) 14 | import(grid) 15 | import(gtable) 16 | importFrom(magrittr,"%>%") 17 | -------------------------------------------------------------------------------- /NEWS.md: -------------------------------------------------------------------------------- 1 | 0.1.0 2 | * Initial release 3 | -------------------------------------------------------------------------------- /R/geom-econodist.R: -------------------------------------------------------------------------------- 1 | draw_key_econodist <- function(data, params, size) { 2 | 3 | grobTree( 4 | rectGrob( 5 | height = 0.5, width = 0.75, 6 | gp = gpar( 7 | fill = alpha( 8 | data$fill %||% params$fill %||% NA, 9 | data$alpha %||% params$alpha %||% NA 10 | ), 11 | col = data$colour %||% params$colour %||% NA 12 | ) 13 | ), 14 | pointsGrob( 15 | x = 0.5, y = 0.5, size = unit(0.25, "npc"), 16 | pch = data$shape, 17 | gp = gpar( 18 | col = data$median_col %||% params$median_col %||% NA 19 | ) 20 | ), 21 | rectGrob( 22 | x = 0.25, 23 | height = 0.75, width = 0.125, 24 | gp = gpar( 25 | fill = data$tenth_col %||% params$tenth_col %||% NA, 26 | col = NA 27 | ) 28 | ), 29 | rectGrob( 30 | x = 0.75, 31 | height = 0.75, width = 0.125, 32 | gp = gpar( 33 | fill = data$ninetieth_col %||% params$ninetieth_col %||% NA, 34 | col = NA 35 | ) 36 | ) 37 | ) 38 | 39 | } 40 | 41 | #' Econodist geom / stat 42 | #' 43 | #' Like [ggplot2::geom_boxplot()] you can either pass in pre-computed 44 | #' values for "ymin", "median", and "ymax" or a single y column 45 | #' which will then use [stat_econodist()] to compute the needed 46 | #' statistics. 47 | #' 48 | #' @param mapping Set of aesthetic mappings created by `aes()` or 49 | #' `aes_()`. If specified and `inherit.aes = TRUE` (the 50 | #' default), it is combined with the default mapping at the top level of the 51 | #' plot. You must supply `mapping` if there is no plot mapping. 52 | #' @param data The data to be displayed in this layer. There are three 53 | #' options: 54 | #' 55 | #' If `NULL`, the default, the data is inherited from the plot 56 | #' data as specified in the call to `ggplot()`. 57 | #' 58 | #' A `data.frame`, or other object, will override the plot 59 | #' data. All objects will be fortified to produce a data frame. See 60 | #' `fortify()` for which variables will be created. 61 | #' 62 | #' A `function` will be called with a single argument, 63 | #' the plot data. The return value must be a `data.frame.`, and 64 | #' will be used as the layer data. 65 | #' @param stat ggplot2 stat to use 66 | #' @param geom ggplot2 geom to use 67 | #' @param position Position adjustment, either as a string, or the result of a call to a position adjustment function. 68 | #' @param tenth_col,median_col,ninetieth_col,median_point_size colors for geom components 69 | #' @param endcap_adjust multipler to make endcaps wider/thinner 70 | #' @param na.rm If `FALSE`, the default, missing values are removed with 71 | #' a warning. If `TRUE`, missing values are silently removed. 72 | #' @param show.legend logical. Should this layer be included in the legends? 73 | #' `NA`, the default, includes if any aesthetics are mapped. 74 | #' `FALSE` never includes, and `TRUE` always includes. 75 | #' It can also be a named logical vector to finely select the aesthetics to 76 | #' display. 77 | #' @param inherit.aes If `FALSE`, overrides the default aesthetics, 78 | #' rather than combining with them. This is most useful for helper functions 79 | #' that define both data and aesthetics and shouldn't inherit behaviour from 80 | #' the default plot specification, e.g. `borders()`. 81 | #' @param ... other arguments passed on to `layer()`. These are 82 | #' often aesthetics, used to set an aesthetic to a fixed value, like 83 | #' `color = "red"` or `size = 3`. They may also be parameters 84 | #' to the paired geom/stat. 85 | #' @export 86 | #' @examples 87 | #' ggplot(mammogram_costs, aes(x = city)) + 88 | #' geom_econodist( 89 | #' aes( 90 | #' ymin = tenth, 91 | #' median = median, 92 | #' ymax = ninetieth 93 | #' ), 94 | #' stat = "identity", 95 | #' ) + 96 | #' scale_y_continuous( 97 | #' expand = c(0,0), 98 | #' position = "right", 99 | #' limits = range(0, 800), 100 | #' label = scales::comma 101 | #' ) + 102 | #' coord_flip() + 103 | #' labs( 104 | #' x = NULL, y = NULL 105 | #' ) 106 | geom_econodist <- function(mapping = NULL, 107 | data = NULL, 108 | stat = "econodist", 109 | position = "dodge2", 110 | tenth_col = econ_tenth, 111 | median_col = econ_median, 112 | ninetieth_col = econ_ninetieth, 113 | median_point_size = NULL, 114 | endcap_adjust = 1.5, 115 | ..., 116 | na.rm = FALSE, 117 | show.legend = NA, 118 | inherit.aes = TRUE) { 119 | 120 | layer( 121 | data = data, 122 | mapping = mapping, 123 | stat = stat, 124 | geom = GeomEconodist, 125 | position = position, 126 | show.legend = show.legend, 127 | inherit.aes = inherit.aes, 128 | params = list( 129 | na.rm = na.rm, 130 | tenth_col = tenth_col, 131 | median_col = median_col, 132 | ninetieth_col = ninetieth_col, 133 | median_point_size = median_point_size, 134 | endcap_adjust = endcap_adjust, 135 | ... 136 | ) 137 | ) 138 | } 139 | 140 | #' @rdname geom_econodist 141 | #' @export 142 | GeomEconodist <- ggproto( 143 | `_class` = "GeomEconodist", 144 | `_inherit` = Geom, 145 | 146 | extra_params = c("na.rm", "width", 147 | "tenth_col", "median_col", "ninetieth_col", 148 | "median_point_size", "endcap_adjust"), 149 | 150 | default_aes = aes( 151 | colour = NA, fill = econ_main, size = 1, weight = 1, 152 | alpha = 0.2, shape = 19, linetype = "solid", stroke = 1 153 | ), 154 | 155 | required_aes = c("x", "ymin", "median", "ymax"), 156 | 157 | setup_data = function(data, params) { 158 | 159 | data$width <- data$width %||% 160 | params$width %||% (ggplot2::resolution(data$x, FALSE) * 0.6) 161 | 162 | data$xmin <- data$x - data$width / 2 163 | data$xmax <- data$x + data$width / 2 164 | 165 | data 166 | 167 | }, 168 | 169 | draw_group = function(data, panel_params, coord, 170 | tenth_col = econ_tenth, 171 | median_col = econ_median, 172 | ninetieth_col = econ_ninetieth, 173 | median_point_size = NULL, 174 | endcap_adjust = 1.5) { 175 | 176 | if (nrow(data) != 1) { 177 | stop( 178 | "It looks like you may have forgotten a grouping aesthetic, i.e. aes(group = ...)", 179 | call. = FALSE 180 | ) 181 | } 182 | 183 | transform( 184 | data, 185 | y = median, 186 | fill = alpha(fill, alpha) 187 | ) -> d_range 188 | 189 | transform( 190 | data, 191 | y = median, 192 | alpha = 1, 193 | colour = median_col, 194 | size = median_point_size %||% (width * 3), 195 | fill = alpha(fill, alpha), 196 | shape = "circle" 197 | ) -> d_median 198 | 199 | transform( 200 | data, 201 | x = xmin, 202 | xend = xmax, 203 | y = ymin, 204 | yend = ymin, 205 | size = size * (endcap_adjust %||% 1.5), 206 | alpha = NA, 207 | colour = tenth_col 208 | ) -> d_tenth 209 | 210 | transform( 211 | data, 212 | x = xmin, 213 | xend = xmax, 214 | y = ymax, 215 | yend = ymax, 216 | size = size * (endcap_adjust %||% 1.5), 217 | alpha = NA, 218 | colour = ninetieth_col 219 | ) -> d_ninetieth 220 | 221 | ggname("geom_econodist", grobTree( 222 | GeomRect$draw_panel(d_range, panel_params, coord), 223 | GeomSegment$draw_panel(d_tenth, panel_params, coord), 224 | GeomSegment$draw_panel(d_ninetieth, panel_params, coord), 225 | GeomPoint$draw_panel(d_median, panel_params, coord) 226 | )) 227 | 228 | }, 229 | 230 | draw_key = draw_key_econodist 231 | 232 | ) 233 | -------------------------------------------------------------------------------- /R/ggeconodist-package.R: -------------------------------------------------------------------------------- 1 | #' Create Diminutive Distribution Charts 2 | #' 3 | #' 'The Economist' has a unique boxplot aesthetic for 4 | #' communicating distrribution characteristics. Tools are provided 5 | #' to create similar charts in 'ggplot2'. 6 | #' 7 | #' @md 8 | #' @name ggeconodist 9 | #' @keywords internal 10 | #' @author Bob Rudis (bob@@rud.is) 11 | #' @import ggplot2 grid gtable 12 | "_PACKAGE" 13 | -------------------------------------------------------------------------------- /R/globals.R: -------------------------------------------------------------------------------- 1 | econ_tenth <- "#39c0d1" 2 | econ_ninetieth <- "#14709f" 3 | econ_plot_bg_col <- "#d7e6ee" 4 | econ_median <- "#6b7a83" 5 | econ_main <- "#6794a7" 6 | econ_text_col <- "#3b454a" 7 | econ_grid_col <- "#63696d" 8 | 9 | 10 | #' Cost of a mammogram in various U.S. Citites (2016, USD) 11 | #' 12 | #' @docType data 13 | #' @export 14 | mammogram_costs <- 15 | structure(list(city = structure(1:11, .Label = c("Houston, TX", 16 | "Los Angeles, CA", "Dallas, TX", "Chicago, IL", "Atlanta, GA", 17 | "Seattle, WA", "Philadelphia, PA", "New York, NY", "Boston, MA", 18 | "Baltimore, MD", "Denver, CO"), class = "factor"), median = c(133.325464181588, 19 | 169.66205927832, 182.665045621407, 195.658588982401, 218.661693362764, 20 | 228.321864044665, 257.991713783213, 264.327954768116, 277, 277.000436737922, 21 | 300.003541118285), ninetieth = c(300.003541118285, 753.00227811943, 22 | 225.998890449604, 325.669566449085, 468.674087276762, 294.989317626506, 23 | 541.337834488131, 490.997296946376, 394.008427861519, 557.013184763748, 24 | 393.337976132863), tenth = c(60.000708223657, 116.328096412847, 25 | 102.654658341104, 115.657644684191, 128.670074009372, 104.996517900353, 26 | 141.333112997084, 164.336217377448, 197.339439795087, 197.008935421806, 27 | 153.335143238235), state = c("TX", "CA", "TX", "IL", "GA", "WA", 28 | "PA", "NY", "MA", "MD", "CO")), class = "data.frame", row.names = c(NA, -11L)) -------------------------------------------------------------------------------- /R/legend-helpers.R: -------------------------------------------------------------------------------- 1 | #' Helper to flush ggplot2 plot components to the left 2 | #' 3 | #' Stolen from the BBC (don't tell Scotland Yard) 4 | #' 5 | #' @param gg ggplot2 plot 6 | #' @param components ggplot2 named gtable components to operate on 7 | #' @family Econodist legend helpers 8 | #' @export 9 | left_align <- function(gg, components){ 10 | grob <- ggplot2::ggplotGrob(gg) 11 | n <- length(components) 12 | grob$layout$l[grob$layout$name %in% components] <- 2 13 | grob 14 | } 15 | 16 | #' Create a legend grob that can be used with econodist charts 17 | #' 18 | #' @param family font family 19 | #' @param label_size size of legend text 20 | #' @param tenth_lab,tenth_col label & color for the tenth bar 21 | #' @param med_lab,med_col label & color for the median point 22 | #' @param ninetieth_lab,ninetieth_col lanbel & color for the ninetieth bar 23 | #' @param label_col color of the legend text 24 | #' @family Econodist legend helpers 25 | #' @export 26 | econodist_legend_grob <- function(family = "EconSansCndLig", 27 | label_size = 10, 28 | tenth_lab = "10th percentile", 29 | tenth_col = econ_tenth, 30 | med_lab = "Median", 31 | med_col = econ_median, 32 | ninetieth_lab = "90th percentile", 33 | ninetieth_col = econ_ninetieth, 34 | label_col = econ_text_col) { 35 | 36 | x_pos <- unit(4, "points") 37 | y_pos <- unit(label_size / 2, "points") 38 | yq <- unit(label_size / 4, "points") 39 | 40 | segmentsGrob( 41 | x0 = x_pos, y0 = y_pos + yq, 42 | x1 = x_pos, y1 = y_pos - yq, 43 | default.units = "points", 44 | gp = gpar( 45 | lwd = 3 * ggplot2::.pt, 46 | lty = "solid", 47 | lineend = "square", 48 | col = tenth_col 49 | ) 50 | ) -> tenth_seg 51 | 52 | x_pos <- x_pos + convertUnit(grobWidth(tenth_seg), "points") + unit(6, "points") 53 | 54 | textGrob( 55 | label = tenth_lab, 56 | x = x_pos, y = y_pos, 57 | hjust = 0, vjust = 0.5, 58 | gp = gpar( 59 | fontfamily = family, 60 | fontsize = label_size, 61 | col = label_col 62 | ) 63 | ) -> tenth_text 64 | 65 | x_pos <- x_pos + convertUnit(grobWidth(tenth_text), "points") + unit(label_size, "points") 66 | 67 | pointsGrob( 68 | x = x_pos, y = y_pos, 69 | size = unit(label_size, "points"), pch = 19, 70 | gp = gpar( 71 | col = med_col, 72 | fill = med_col 73 | ) 74 | ) -> med_pt 75 | 76 | x_pos <- x_pos + convertUnit(grobWidth(med_pt), "points") + unit(8, "points") 77 | 78 | textGrob( 79 | label = med_lab, 80 | x = x_pos, y = y_pos, 81 | hjust = 0, vjust = 0.5, 82 | gp = gpar( 83 | fontfamily = family, 84 | fontsize = label_size, 85 | col = label_col 86 | ) 87 | ) -> med_text 88 | 89 | x_pos <- x_pos + convertUnit(grobWidth(med_text), "points") + unit(label_size, "points") 90 | 91 | segmentsGrob( 92 | x0 = x_pos, y0 = y_pos - yq, 93 | x1 = x_pos, y1 = y_pos + yq, 94 | gp = gpar( 95 | lwd = 3 * ggplot2::.pt, 96 | lty = "solid", 97 | lineend = "square", 98 | col = ninetieth_col 99 | ) 100 | ) -> ninth_seg 101 | 102 | x_pos <- x_pos + grobWidth(ninth_seg) + unit(8, "points") 103 | 104 | textGrob( 105 | label = ninetieth_lab, 106 | x = x_pos, y = y_pos, 107 | hjust = 0, vjust = 0.5, 108 | gp = gpar( 109 | fontfamily = family, 110 | fontsize = label_size, 111 | col = label_col 112 | ) 113 | ) -> ninth_text 114 | 115 | width <- x_pos + grobWidth(ninth_text) 116 | 117 | vp <- viewport(x = 0, just = "left", default.units = "points", width = width) 118 | 119 | gTree( 120 | name = "econodist-legend", 121 | children = gList( 122 | tenth_seg, tenth_text, 123 | med_pt, med_text, 124 | ninth_seg, ninth_text 125 | ), 126 | childrenvp = vp, 127 | vp = viewport(x = 0, just = "left", width = width) 128 | ) 129 | 130 | } 131 | 132 | #' Helper utility to get an econodist legend into a ggplot2 plot 133 | #' 134 | #' @param gg ggplot2 plot object to add 135 | #' @param legend legend grob (any grob, really) 136 | #' @param below which named gtable element to stick it below? 137 | #' @param just legend position: "`left`" (aligned with left veritcal axis), 138 | #' "`center`" (center of plot panel), or "`right`" (aligned with right 139 | #' vertical axis). Uses [pmatch()] so partial matching is supported. 140 | #' @param legend_height height of the legend row 141 | #' @param spacer height of the spacer that is put below `legend`? 142 | #' @family Econodist legend helpers 143 | #' @export 144 | add_econodist_legend <- function(gg, legend, below = "subtitle", 145 | just = c("left", "center", "right"), 146 | legend_height = unit(16, "points"), 147 | spacer = unit(10, "points")) { 148 | 149 | choices <- c("left", "center", "right") 150 | just <- choices[pmatch(just[1], choices, duplicates.ok = FALSE)] 151 | 152 | if (!inherits(gg, "gtable")) gg <- ggplot2::ggplotGrob(gg) 153 | 154 | st <- gg$layout[gg$layout$name == below,] 155 | 156 | gtable::gtable_add_rows( 157 | gtable::gtable_add_grob( 158 | gtable::gtable_add_rows(gg, legend_height, st$b), 159 | legend, t = st$b + 1, l = st$l, b = st$b + 1, r = st$r, 160 | name = "econodist-legend" 161 | ), 162 | spacer, st$b + 1 163 | ) -> gg2 164 | 165 | w <- gg2$grobs[[which(gg2$layout$name == "econodist-legend")]]$vp$width 166 | hw <- unit(as.numeric(convertUnit(w, "points"))/2, "points") 167 | switch( 168 | just, 169 | left = gg2$grobs[[which(gg2$layout$name == "econodist-legend")]]$vp$x <- 170 | unit(0, "npc"), 171 | right = gg2$grobs[[which(gg2$layout$name == "econodist-legend")]]$vp$x <- 172 | unit(1, "npc") - w, 173 | center = gg2$grobs[[which(gg2$layout$name == "econodist-legend")]]$vp$x <- 174 | unit(0.5, "npc") - hw 175 | ) 176 | 177 | gg2 178 | 179 | } 180 | -------------------------------------------------------------------------------- /R/stat-econodist.R: -------------------------------------------------------------------------------- 1 | #' @rdname geom_econodist 2 | #' @export 3 | stat_econodist <- function(mapping = NULL, data = NULL, 4 | geom = "econodist", position = "dodge2", 5 | ..., 6 | na.rm = FALSE, 7 | show.legend = NA, 8 | inherit.aes = TRUE) { 9 | layer( 10 | data = data, 11 | mapping = mapping, 12 | stat = StatEconodist, 13 | geom = geom, 14 | position = position, 15 | show.legend = show.legend, 16 | inherit.aes = inherit.aes, 17 | params = list( 18 | na.rm = na.rm, 19 | ... 20 | ) 21 | ) 22 | } 23 | 24 | #' @rdname geom_econodist 25 | #' @export 26 | StatEconodist <- ggproto( 27 | `_class` = "StatEconodist", 28 | `_inherit` = Stat, 29 | 30 | required_aes = c("y"), 31 | 32 | setup_data = function(data, params) { 33 | 34 | data$x <- data$x %||% 0 35 | 36 | ggplot2::remove_missing( 37 | data, 38 | na.rm = FALSE, 39 | vars = "x", 40 | name = "stat_econodist" 41 | ) 42 | 43 | }, 44 | 45 | setup_params = function(data, params) { 46 | 47 | params$width <- params$width %||% (resolution(data$x %||% 0) * 0.75) 48 | 49 | if (is.double(data$x) && !has_groups(data) && any(data$x != data$x[1L])) { 50 | warning("Continuous x aesthetic -- did you forget aes(group=...)?", call. = FALSE) 51 | } 52 | 53 | params 54 | 55 | }, 56 | 57 | compute_group = function(data, scales, width = NULL, na.rm = FALSE) { 58 | 59 | qs <- c(0.10, 0.5, 0.90) 60 | 61 | stats <- as.numeric(stats::quantile(data$y, qs)) 62 | names(stats) <- c("ymin", "median", "ymax") 63 | 64 | if (length(unique(data$x)) > 1) width <- diff(range(data$x)) * 0.9 65 | 66 | xdf <- new_data_frame(as.list(stats)) 67 | xdf$x <- if (is.factor(data$x)) data$x[1] else mean(range(data$x)) 68 | xdf$width <- width 69 | 70 | xdf 71 | 72 | } 73 | 74 | ) 75 | -------------------------------------------------------------------------------- /R/theme-econ.R: -------------------------------------------------------------------------------- 1 | #' A more current Economist-style ggplot2 theme 2 | #' 3 | #' @param econ_text_col color for text elements 4 | #' @param econ_plot_bg_col plot background color 5 | #' @param econ_grid_col plot grid color 6 | #' @param econ_font core plot font 7 | #' @param light_font light font used in various polaces 8 | #' @param bold_font bold font used in various places 9 | #' @note You *need* their fonts installed. You can get them from 10 | #' [here](https://github.com/economist-components/component-typography) 11 | #' @export 12 | theme_econodist <- function(econ_text_col = "#3b454a", 13 | econ_plot_bg_col = "#d7e6ee", 14 | econ_grid_col = "#bbcad2", 15 | econ_font = "EconSansCndReg", 16 | light_font = "EconSansCndLig", 17 | bold_font = "EconSansCndBol") { 18 | 19 | theme_minimal(base_family = econ_font) + 20 | theme( 21 | plot.title = element_text(family = bold_font), 22 | plot.subtitle = element_text(family = light_font, size = 12, margin = margin(t = -5)), 23 | plot.caption = element_text(family = light_font, size = 10, colour = econ_text_col, lineheight = 1.1), 24 | plot.background = element_rect(fill = econ_plot_bg_col, colour = econ_plot_bg_col), 25 | panel.background = element_rect(fill = econ_plot_bg_col, colour = econ_plot_bg_col), 26 | axis.ticks = element_blank(), 27 | axis.ticks.x = element_blank(), 28 | axis.ticks.y = element_blank(), 29 | axis.text = element_text(family = light_font, colour = econ_text_col), 30 | axis.text.x = element_text(family = light_font, size = 10, colour = econ_text_col), 31 | axis.text.y = element_text(hjust = 0, family = light_font, size = 10, colour = econ_text_col), 32 | axis.line.x = element_blank(), 33 | axis.line.y = element_line(colour = econ_grid_col, size = 0.5), 34 | plot.margin = margin(10, 15, 10, 12), 35 | panel.grid.major.x = element_line(linetype = "solid", size = 0.4, colour = econ_grid_col), 36 | panel.grid.major.y = element_line(linetype = "solid", size = 0.4, colour = econ_grid_col), 37 | panel.grid.minor.x = element_blank(), 38 | panel.grid.minor.y = element_blank() 39 | ) 40 | } 41 | -------------------------------------------------------------------------------- /R/utils-infix-helpers.R: -------------------------------------------------------------------------------- 1 | `%l0%` <- function(x, y) if (length(x) == 0) y else x 2 | `%||%` <- function(x, y) if (is.null(x)) y else x 3 | `%@%` <- function(x, name) attr(x, name, exact = TRUE) 4 | `%nin%` <- function(x, table) match(x, table, nomatch = 0) == 0 5 | -------------------------------------------------------------------------------- /R/utils-pipe.R: -------------------------------------------------------------------------------- 1 | #' Pipe operator 2 | #' 3 | #' See \code{magrittr::\link[magrittr:pipe]{\%>\%}} for details. 4 | #' 5 | #' @name %>% 6 | #' @rdname pipe 7 | #' @keywords internal 8 | #' @export 9 | #' @importFrom magrittr %>% 10 | #' @usage lhs \%>\% rhs 11 | NULL 12 | -------------------------------------------------------------------------------- /R/utils.R: -------------------------------------------------------------------------------- 1 | 2 | ggname <- function(prefix, grob) { 3 | grob$name <- grobName(grob, prefix) 4 | grob 5 | } 6 | 7 | new_data_frame <- function(x = list(), n = NULL) { 8 | if (length(x) != 0 && is.null(names(x))) stop("Elements must be named", call. = FALSE) 9 | lengths <- vapply(x, length, integer(1)) 10 | if (is.null(n)) { 11 | n <- if (length(x) == 0 || min(lengths) == 0) 0 else max(lengths) 12 | } 13 | for (i in seq_along(x)) { 14 | if (lengths[i] == n) next 15 | if (lengths[i] != 1) stop("Elements must equal the number of rows or 1", call. = FALSE) 16 | x[[i]] <- rep(x[[i]], n) 17 | } 18 | 19 | class(x) <- "data.frame" 20 | attr(x, "row.names") <- .set_row_names(n) 21 | x 22 | } 23 | 24 | data_frame <- function(...) { 25 | new_data_frame(list(...)) 26 | } 27 | -------------------------------------------------------------------------------- /README.Rmd: -------------------------------------------------------------------------------- 1 | --- 2 | output: rmarkdown::github_document 3 | editor_options: 4 | chunk_output_type: console 5 | --- 6 | ```{r pkg-knitr-opts, include=FALSE} 7 | hrbrpkghelpr::global_opts() 8 | ``` 9 | 10 | ```{r badges, results='asis', echo=FALSE, cache=FALSE} 11 | hrbrpkghelpr::stinking_badges() 12 | ``` 13 | 14 | # ggeconodist 15 | 16 | Create Diminutive Distribution Charts 17 | 18 | ## Description 19 | 20 | 'The Economist' has a unique boxplot aesthetic f or 21 | communicating distrribution characteristics. Tools are provided 22 | to create similar charts in 'ggplot2'. 23 | 24 | Inspired by: 25 | 26 | ## What's Inside The Tin 27 | 28 | ```{r ingredients, results='asis', echo=FALSE, cache=FALSE} 29 | hrbrpkghelpr::describe_ingredients() 30 | ``` 31 | 32 | The following functions are implemented: 33 | 34 | ## Installation 35 | 36 | ```{r install-ex, results='asis', echo=FALSE, cache=FALSE} 37 | hrbrpkghelpr::install_block() 38 | ``` 39 | 40 | ## Usage 41 | 42 | ```{r lib-ex} 43 | library(ggeconodist) 44 | 45 | # current version 46 | packageVersion("ggeconodist") 47 | 48 | ``` 49 | 50 | ### The whole shebang 51 | 52 | **YOU WILL NEED** to install [these fonts](https://github.com/economist-components/component-typography) to use the built-in theme. More on how to do that at some point. 53 | 54 | ```{r mam} 55 | ggplot(mammogram_costs, aes(x = city)) + 56 | geom_econodist( 57 | aes(ymin = tenth, median = median, ymax = ninetieth), 58 | stat = "identity", show.legend = TRUE 59 | ) + 60 | scale_y_continuous(expand = c(0,0), position = "right", limits = range(0, 800)) + 61 | coord_flip() + 62 | labs( 63 | x = NULL, y = NULL, 64 | title = "Mammoscams", 65 | subtitle = "United States, prices for a mammogram*\nBy metro area, 2016, $", 66 | caption = "*For three large insurance companies\nSource: Health Care Cost Institute" 67 | ) + 68 | theme_econodist() -> gg 69 | 70 | grid.newpage() 71 | left_align(gg, c("subtitle", "title", "caption")) %>% 72 | add_econodist_legend(econodist_legend_grob(), below = "subtitle") %>% 73 | grid.draw() 74 | ``` 75 | 76 | ```{r mpg} 77 | library(dplyr) 78 | library(patchwork) 79 | library(hrbrthemes) 80 | library(gapminder) 81 | 82 | p <- ggplot(mpg, aes(class, hwy)) + theme_ipsum_rc() 83 | 84 | (p + geom_boxplot()) + 85 | (p + geom_econodist(width = 0.25)) + 86 | plot_layout(ncol = 1) 87 | 88 | (p + geom_boxplot() + coord_flip()) + 89 | (p + geom_econodist(tenth_col = ft_cols$blue, ninetieth_col = ft_cols$red) + 90 | coord_flip()) + 91 | plot_layout(ncol = 1) 92 | 93 | (p + geom_boxplot(aes(fill = factor(drv)))) + 94 | (p + geom_econodist(aes(fill = factor(drv)))) + 95 | plot_layout(ncol = 1) 96 | ``` 97 | 98 | ```{r gm, fig.width=600/72, fig.height=700/72} 99 | gapminder %>% 100 | filter(year %in% c(1952, 1962, 1972, 1982, 1992, 2002)) %>% 101 | filter(continent != "Oceania") %>% 102 | ggplot(aes(x = factor(year), y = lifeExp, fill = continent)) + 103 | geom_econodist( 104 | median_point_size = 1.2, 105 | tenth_col = "#b07aa1", 106 | ninetieth_col = "#591a4f", 107 | show.legend = FALSE 108 | ) + 109 | ggthemes::scale_fill_tableau(name = NULL) + 110 | coord_flip() + 111 | labs( 112 | x = "Year", title = "Life Expectancy", y = NULL, 113 | caption = "Example borrowed from @cmdline_tips" 114 | ) + 115 | facet_wrap(~continent, nrow = 4) + 116 | theme_ipsum_rc() -> gmgg 117 | 118 | grid.newpage() 119 | gmgg %>% 120 | add_econodist_legend( 121 | econodist_legend_grob( 122 | tenth_col = "#b07aa1", 123 | ninetieth_col = "#591a4f", 124 | ), 125 | below = "axis-b-1-4", 126 | just = "right" 127 | ) %>% 128 | grid.draw() 129 | ``` 130 | 131 | ## ggeconodist Metrics 132 | 133 | ```{r cloc, echo = FALSE} 134 | cloc::cloc_pkg_md() 135 | ``` 136 | 137 | ## Code of Conduct 138 | 139 | Please note that this project is released with a Contributor Code of Conduct. By participating in this project you agree to abide by its terms. 140 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | 2 | [![Project Status: Active – The project has reached a stable, usable 3 | state and is being actively 4 | developed.](https://www.repostatus.org/badges/latest/active.svg)](https://www.repostatus.org/#active) 5 | [![Signed 6 | by](https://img.shields.io/badge/Keybase-Verified-brightgreen.svg)](https://keybase.io/hrbrmstr) 7 | ![Signed commit 8 | %](https://img.shields.io/badge/Signed_Commits-100%25-lightgrey.svg) 9 | [![Linux build 10 | Status](https://travis-ci.org/hrbrmstr/ggeconodist.svg?branch=master)](https://travis-ci.org/hrbrmstr/ggeconodist) 11 | [![Coverage 12 | Status](https://codecov.io/gh/hrbrmstr/ggeconodist/branch/master/graph/badge.svg)](https://codecov.io/gh/hrbrmstr/ggeconodist) 13 | ![Minimal R 14 | Version](https://img.shields.io/badge/R%3E%3D-3.2.0-blue.svg) 15 | ![License](https://img.shields.io/badge/License-MIT-blue.svg) 16 | 17 | # ggeconodist 18 | 19 | Create Diminutive Distribution Charts 20 | 21 | ## Description 22 | 23 | ‘The Economist’ has a unique boxplot aesthetic f or communicating 24 | distrribution characteristics. Tools are provided to create similar 25 | charts in ‘ggplot2’. 26 | 27 | Inspired by: 28 | 29 | 30 | ## What’s Inside The Tin 31 | 32 | - `add_econodist_legend`: Helper utility to get an econodist legend 33 | into a ggplot2 plot 34 | - `econodist_legend_grob`: Create a legend grob that can be used with 35 | econodist charts 36 | - `geom_econodist`: Econodist geom / stat 37 | - `left_align`: Helper to flush ggplot2 plot components to the left 38 | - `mammogram_costs`: Cost of a mammogram in various U.S. Citites 39 | (2016, USD) 40 | - `theme_econodist`: A more current Economist-style ggplot2 theme 41 | 42 | The following functions are implemented: 43 | 44 | ## Installation 45 | 46 | ``` r 47 | install.packages("ggeconodist", repos = "https://cinc.rud.is") 48 | # or 49 | remotes::install_git("https://git.rud.is/hrbrmstr/ggeconodist.git") 50 | # or 51 | remotes::install_git("https://git.sr.ht/~hrbrmstr/ggeconodist") 52 | # or 53 | remotes::install_gitlab("hrbrmstr/ggeconodist") 54 | # or 55 | remotes::install_bitbucket("hrbrmstr/ggeconodist") 56 | # or 57 | remotes::install_github("hrbrmstr/ggeconodist") 58 | ``` 59 | 60 | NOTE: To use the ‘remotes’ install options you will need to have the 61 | [{remotes} package](https://github.com/r-lib/remotes) installed. 62 | 63 | ## Usage 64 | 65 | ``` r 66 | library(ggeconodist) 67 | 68 | # current version 69 | packageVersion("ggeconodist") 70 | ## [1] '0.1.0' 71 | ``` 72 | 73 | ### The whole shebang 74 | 75 | **YOU WILL NEED** to install [these 76 | fonts](https://github.com/economist-components/component-typography) to 77 | use the built-in theme. More on how to do that at some point. 78 | 79 | ``` r 80 | ggplot(mammogram_costs, aes(x = city)) + 81 | geom_econodist( 82 | aes(ymin = tenth, median = median, ymax = ninetieth), 83 | stat = "identity", show.legend = TRUE 84 | ) + 85 | scale_y_continuous(expand = c(0,0), position = "right", limits = range(0, 800)) + 86 | coord_flip() + 87 | labs( 88 | x = NULL, y = NULL, 89 | title = "Mammoscams", 90 | subtitle = "United States, prices for a mammogram*\nBy metro area, 2016, $", 91 | caption = "*For three large insurance companies\nSource: Health Care Cost Institute" 92 | ) + 93 | theme_econodist() -> gg 94 | 95 | grid.newpage() 96 | left_align(gg, c("subtitle", "title", "caption")) %>% 97 | add_econodist_legend(econodist_legend_grob(), below = "subtitle") %>% 98 | grid.draw() 99 | ``` 100 | 101 | 102 | 103 | ``` r 104 | library(dplyr) 105 | library(patchwork) 106 | library(hrbrthemes) 107 | library(gapminder) 108 | 109 | p <- ggplot(mpg, aes(class, hwy)) + theme_ipsum_rc() 110 | 111 | (p + geom_boxplot()) + 112 | (p + geom_econodist(width = 0.25)) + 113 | plot_layout(ncol = 1) 114 | ``` 115 | 116 | 117 | 118 | ``` r 119 | 120 | (p + geom_boxplot() + coord_flip()) + 121 | (p + geom_econodist(tenth_col = ft_cols$blue, ninetieth_col = ft_cols$red) + 122 | coord_flip()) + 123 | plot_layout(ncol = 1) 124 | ``` 125 | 126 | 127 | 128 | ``` r 129 | 130 | (p + geom_boxplot(aes(fill = factor(drv)))) + 131 | (p + geom_econodist(aes(fill = factor(drv)))) + 132 | plot_layout(ncol = 1) 133 | ``` 134 | 135 | 136 | 137 | ``` r 138 | gapminder %>% 139 | filter(year %in% c(1952, 1962, 1972, 1982, 1992, 2002)) %>% 140 | filter(continent != "Oceania") %>% 141 | ggplot(aes(x = factor(year), y = lifeExp, fill = continent)) + 142 | geom_econodist( 143 | median_point_size = 1.2, 144 | tenth_col = "#b07aa1", 145 | ninetieth_col = "#591a4f", 146 | show.legend = FALSE 147 | ) + 148 | ggthemes::scale_fill_tableau(name = NULL) + 149 | coord_flip() + 150 | labs( 151 | x = "Year", title = "Life Expectancy", y = NULL, 152 | caption = "Example borrowed from @cmdline_tips" 153 | ) + 154 | facet_wrap(~continent, nrow = 4) + 155 | theme_ipsum_rc() -> gmgg 156 | 157 | grid.newpage() 158 | gmgg %>% 159 | add_econodist_legend( 160 | econodist_legend_grob( 161 | tenth_col = "#b07aa1", 162 | ninetieth_col = "#591a4f", 163 | ), 164 | below = "axis-b-1-4", 165 | just = "right" 166 | ) %>% 167 | grid.draw() 168 | ``` 169 | 170 | 171 | 172 | ## ggeconodist Metrics 173 | 174 | | Lang | \# Files | (%) | LoC | (%) | Blank lines | (%) | \# Lines | (%) | 175 | | :--- | -------: | ---: | --: | ---: | ----------: | ---: | -------: | ---: | 176 | | R | 10 | 0.91 | 398 | 0.85 | 76 | 0.72 | 137 | 0.77 | 177 | | Rmd | 1 | 0.09 | 69 | 0.15 | 30 | 0.28 | 40 | 0.23 | 178 | 179 | ## Code of Conduct 180 | 181 | Please note that this project is released with a Contributor Code of 182 | Conduct. By participating in this project you agree to abide by its 183 | terms. 184 | -------------------------------------------------------------------------------- /ggeconodist.Rproj: -------------------------------------------------------------------------------- 1 | Version: 1.0 2 | 3 | RestoreWorkspace: Default 4 | SaveWorkspace: Default 5 | AlwaysSaveHistory: Default 6 | 7 | EnableCodeIndexing: Yes 8 | UseSpacesForTab: Yes 9 | NumSpacesForTab: 2 10 | Encoding: UTF-8 11 | 12 | RnwWeave: Sweave 13 | LaTeX: pdfLaTeX 14 | 15 | StripTrailingWhitespace: Yes 16 | 17 | BuildType: Package 18 | PackageUseDevtools: Yes 19 | PackageInstallArgs: --no-multiarch --with-keep.source 20 | PackageBuildArgs: --resave-data 21 | PackageRoxygenize: rd,collate,namespace 22 | -------------------------------------------------------------------------------- /inst/tinytest/test_ggeconodist.R: -------------------------------------------------------------------------------- 1 | library(ggeconodist) 2 | 3 | ggplot(mammogram_costs, aes(x = city)) + 4 | geom_econodist( 5 | aes(ymin = tenth, median = median, ymax = ninetieth), 6 | stat = "identity", 7 | ) -> gg 8 | 9 | gb <- ggplotGrob(gg) 10 | 11 | expect_true(inherits(gb, "gtable")) 12 | expect_true(identical(dim(gb$layout), c(18L, 7L))) 13 | 14 | add_econodist_legend( 15 | gg, 16 | econodist_legend_grob( 17 | tenth_col = "#b07aa1", 18 | ninetieth_col = "#591a4f", 19 | ), 20 | below = "subtitle", 21 | just = "right" 22 | ) -> gt 23 | 24 | expect_true("econodist-legend" %in% gt$layout$name) 25 | -------------------------------------------------------------------------------- /man/add_econodist_legend.Rd: -------------------------------------------------------------------------------- 1 | % Generated by roxygen2: do not edit by hand 2 | % Please edit documentation in R/legend-helpers.R 3 | \name{add_econodist_legend} 4 | \alias{add_econodist_legend} 5 | \title{Helper utility to get an econodist legend into a ggplot2 plot} 6 | \usage{ 7 | add_econodist_legend(gg, legend, below = "subtitle", just = c("left", 8 | "center", "right"), legend_height = unit(16, "points"), 9 | spacer = unit(10, "points")) 10 | } 11 | \arguments{ 12 | \item{gg}{ggplot2 plot object to add} 13 | 14 | \item{legend}{legend grob (any grob, really)} 15 | 16 | \item{below}{which named gtable element to stick it below?} 17 | 18 | \item{just}{legend position: "\code{left}" (aligned with left veritcal axis), 19 | "\code{center}" (center of plot panel), or "\code{right}" (aligned with right 20 | vertical axis). Uses \code{\link[=pmatch]{pmatch()}} so partial matching is supported.} 21 | 22 | \item{legend_height}{height of the legend row} 23 | 24 | \item{spacer}{height of the spacer that is put below \code{legend}?} 25 | } 26 | \description{ 27 | Helper utility to get an econodist legend into a ggplot2 plot 28 | } 29 | \seealso{ 30 | Other Econodist legend helpers: \code{\link{econodist_legend_grob}}, 31 | \code{\link{left_align}} 32 | } 33 | \concept{Econodist legend helpers} 34 | -------------------------------------------------------------------------------- /man/econodist_legend_grob.Rd: -------------------------------------------------------------------------------- 1 | % Generated by roxygen2: do not edit by hand 2 | % Please edit documentation in R/legend-helpers.R 3 | \name{econodist_legend_grob} 4 | \alias{econodist_legend_grob} 5 | \title{Create a legend grob that can be used with econodist charts} 6 | \usage{ 7 | econodist_legend_grob(family = "EconSansCndLig", label_size = 10, 8 | tenth_lab = "10th percentile", tenth_col = econ_tenth, 9 | med_lab = "Median", med_col = econ_median, 10 | ninetieth_lab = "90th percentile", ninetieth_col = econ_ninetieth, 11 | label_col = econ_text_col) 12 | } 13 | \arguments{ 14 | \item{family}{font family} 15 | 16 | \item{label_size}{size of legend text} 17 | 18 | \item{tenth_lab, tenth_col}{label & color for the tenth bar} 19 | 20 | \item{med_lab, med_col}{label & color for the median point} 21 | 22 | \item{ninetieth_lab, ninetieth_col}{lanbel & color for the ninetieth bar} 23 | 24 | \item{label_col}{color of the legend text} 25 | } 26 | \description{ 27 | Create a legend grob that can be used with econodist charts 28 | } 29 | \seealso{ 30 | Other Econodist legend helpers: \code{\link{add_econodist_legend}}, 31 | \code{\link{left_align}} 32 | } 33 | \concept{Econodist legend helpers} 34 | -------------------------------------------------------------------------------- /man/figures/README-gm-1.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/hrbrmstr/ggeconodist/a4b1fa18dfeadad95ade40505e4453f10f6615bb/man/figures/README-gm-1.png -------------------------------------------------------------------------------- /man/figures/README-mam-1.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/hrbrmstr/ggeconodist/a4b1fa18dfeadad95ade40505e4453f10f6615bb/man/figures/README-mam-1.png -------------------------------------------------------------------------------- /man/figures/README-mpg-1.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/hrbrmstr/ggeconodist/a4b1fa18dfeadad95ade40505e4453f10f6615bb/man/figures/README-mpg-1.png -------------------------------------------------------------------------------- /man/figures/README-mpg-2.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/hrbrmstr/ggeconodist/a4b1fa18dfeadad95ade40505e4453f10f6615bb/man/figures/README-mpg-2.png -------------------------------------------------------------------------------- /man/figures/README-mpg-3.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/hrbrmstr/ggeconodist/a4b1fa18dfeadad95ade40505e4453f10f6615bb/man/figures/README-mpg-3.png -------------------------------------------------------------------------------- /man/geom_econodist.Rd: -------------------------------------------------------------------------------- 1 | % Generated by roxygen2: do not edit by hand 2 | % Please edit documentation in R/geom-econodist.R, R/stat-econodist.R 3 | \docType{data} 4 | \name{geom_econodist} 5 | \alias{geom_econodist} 6 | \alias{GeomEconodist} 7 | \alias{stat_econodist} 8 | \alias{StatEconodist} 9 | \title{Econodist geom / stat} 10 | \format{An object of class \code{GeomEconodist} (inherits from \code{Geom}, \code{ggproto}, \code{gg}) of length 7.} 11 | \usage{ 12 | geom_econodist(mapping = NULL, data = NULL, stat = "econodist", 13 | position = "dodge2", tenth_col = econ_tenth, 14 | median_col = econ_median, ninetieth_col = econ_ninetieth, 15 | median_point_size = NULL, endcap_adjust = 1.5, ..., na.rm = FALSE, 16 | show.legend = NA, inherit.aes = TRUE) 17 | 18 | GeomEconodist 19 | 20 | stat_econodist(mapping = NULL, data = NULL, geom = "econodist", 21 | position = "dodge2", ..., na.rm = FALSE, show.legend = NA, 22 | inherit.aes = TRUE) 23 | 24 | StatEconodist 25 | } 26 | \arguments{ 27 | \item{mapping}{Set of aesthetic mappings created by \code{aes()} or 28 | \code{aes_()}. If specified and \code{inherit.aes = TRUE} (the 29 | default), it is combined with the default mapping at the top level of the 30 | plot. You must supply \code{mapping} if there is no plot mapping.} 31 | 32 | \item{data}{The data to be displayed in this layer. There are three 33 | options: 34 | 35 | If \code{NULL}, the default, the data is inherited from the plot 36 | data as specified in the call to \code{ggplot()}. 37 | 38 | A \code{data.frame}, or other object, will override the plot 39 | data. All objects will be fortified to produce a data frame. See 40 | \code{fortify()} for which variables will be created. 41 | 42 | A \code{function} will be called with a single argument, 43 | the plot data. The return value must be a \code{data.frame.}, and 44 | will be used as the layer data.} 45 | 46 | \item{stat}{ggplot2 stat to use} 47 | 48 | \item{position}{Position adjustment, either as a string, or the result of a call to a position adjustment function.} 49 | 50 | \item{tenth_col, median_col, ninetieth_col, median_point_size}{colors for geom components} 51 | 52 | \item{endcap_adjust}{multipler to make endcaps wider/thinner} 53 | 54 | \item{...}{other arguments passed on to \code{layer()}. These are 55 | often aesthetics, used to set an aesthetic to a fixed value, like 56 | \code{color = "red"} or \code{size = 3}. They may also be parameters 57 | to the paired geom/stat.} 58 | 59 | \item{na.rm}{If \code{FALSE}, the default, missing values are removed with 60 | a warning. If \code{TRUE}, missing values are silently removed.} 61 | 62 | \item{show.legend}{logical. Should this layer be included in the legends? 63 | \code{NA}, the default, includes if any aesthetics are mapped. 64 | \code{FALSE} never includes, and \code{TRUE} always includes. 65 | It can also be a named logical vector to finely select the aesthetics to 66 | display.} 67 | 68 | \item{inherit.aes}{If \code{FALSE}, overrides the default aesthetics, 69 | rather than combining with them. This is most useful for helper functions 70 | that define both data and aesthetics and shouldn't inherit behaviour from 71 | the default plot specification, e.g. \code{borders()}.} 72 | 73 | \item{geom}{ggplot2 geom to use} 74 | } 75 | \description{ 76 | Like \code{\link[ggplot2:geom_boxplot]{ggplot2::geom_boxplot()}} you can either pass in pre-computed 77 | values for "ymin", "median", and "ymax" or a single y column 78 | which will then use \code{\link[=stat_econodist]{stat_econodist()}} to compute the needed 79 | statistics. 80 | } 81 | \examples{ 82 | ggplot(mammogram_costs, aes(x = city)) + 83 | geom_econodist( 84 | aes( 85 | ymin = tenth, 86 | median = median, 87 | ymax = ninetieth 88 | ), 89 | stat = "identity", 90 | ) + 91 | scale_y_continuous( 92 | expand = c(0,0), 93 | position = "right", 94 | limits = range(0, 800), 95 | label = scales::comma 96 | ) + 97 | coord_flip() + 98 | labs( 99 | x = NULL, y = NULL 100 | ) 101 | } 102 | \keyword{datasets} 103 | -------------------------------------------------------------------------------- /man/ggeconodist.Rd: -------------------------------------------------------------------------------- 1 | % Generated by roxygen2: do not edit by hand 2 | % Please edit documentation in R/ggeconodist-package.R 3 | \docType{package} 4 | \name{ggeconodist} 5 | \alias{ggeconodist} 6 | \alias{ggeconodist-package} 7 | \title{Create Diminutive Distribution Charts} 8 | \description{ 9 | 'The Economist' has a unique boxplot aesthetic for 10 | communicating distrribution characteristics. Tools are provided 11 | to create similar charts in 'ggplot2'. 12 | } 13 | \seealso{ 14 | Useful links: 15 | \itemize{ 16 | \item \url{https://gitlab.com/hrbrmstr/ggeconodist} 17 | \item Report bugs at \url{https://gitlab.com/hrbrmstr/ggeconodist/issues} 18 | } 19 | 20 | } 21 | \author{ 22 | Bob Rudis (bob@rud.is) 23 | } 24 | \keyword{internal} 25 | -------------------------------------------------------------------------------- /man/left_align.Rd: -------------------------------------------------------------------------------- 1 | % Generated by roxygen2: do not edit by hand 2 | % Please edit documentation in R/legend-helpers.R 3 | \name{left_align} 4 | \alias{left_align} 5 | \title{Helper to flush ggplot2 plot components to the left} 6 | \usage{ 7 | left_align(gg, components) 8 | } 9 | \arguments{ 10 | \item{gg}{ggplot2 plot} 11 | 12 | \item{components}{ggplot2 named gtable components to operate on} 13 | } 14 | \description{ 15 | Stolen from the BBC (don't tell Scotland Yard) 16 | } 17 | \seealso{ 18 | Other Econodist legend helpers: \code{\link{add_econodist_legend}}, 19 | \code{\link{econodist_legend_grob}} 20 | } 21 | \concept{Econodist legend helpers} 22 | -------------------------------------------------------------------------------- /man/mammogram_costs.Rd: -------------------------------------------------------------------------------- 1 | % Generated by roxygen2: do not edit by hand 2 | % Please edit documentation in R/globals.R 3 | \docType{data} 4 | \name{mammogram_costs} 5 | \alias{mammogram_costs} 6 | \title{Cost of a mammogram in various U.S. Citites (2016, USD)} 7 | \format{An object of class \code{data.frame} with 11 rows and 5 columns.} 8 | \usage{ 9 | mammogram_costs 10 | } 11 | \description{ 12 | Cost of a mammogram in various U.S. Citites (2016, USD) 13 | } 14 | \keyword{datasets} 15 | -------------------------------------------------------------------------------- /man/pipe.Rd: -------------------------------------------------------------------------------- 1 | % Generated by roxygen2: do not edit by hand 2 | % Please edit documentation in R/utils-pipe.R 3 | \name{\%>\%} 4 | \alias{\%>\%} 5 | \title{Pipe operator} 6 | \usage{ 7 | lhs \%>\% rhs 8 | } 9 | \description{ 10 | See \code{magrittr::\link[magrittr:pipe]{\%>\%}} for details. 11 | } 12 | \keyword{internal} 13 | -------------------------------------------------------------------------------- /man/theme_econodist.Rd: -------------------------------------------------------------------------------- 1 | % Generated by roxygen2: do not edit by hand 2 | % Please edit documentation in R/theme-econ.R 3 | \name{theme_econodist} 4 | \alias{theme_econodist} 5 | \title{A more current Economist-style ggplot2 theme} 6 | \usage{ 7 | theme_econodist(econ_text_col = "#3b454a", 8 | econ_plot_bg_col = "#d7e6ee", econ_grid_col = "#bbcad2", 9 | econ_font = "EconSansCndReg", light_font = "EconSansCndLig", 10 | bold_font = "EconSansCndBol") 11 | } 12 | \arguments{ 13 | \item{econ_text_col}{color for text elements} 14 | 15 | \item{econ_plot_bg_col}{plot background color} 16 | 17 | \item{econ_grid_col}{plot grid color} 18 | 19 | \item{econ_font}{core plot font} 20 | 21 | \item{light_font}{light font used in various polaces} 22 | 23 | \item{bold_font}{bold font used in various places} 24 | } 25 | \description{ 26 | A more current Economist-style ggplot2 theme 27 | } 28 | \note{ 29 | You \emph{need} their fonts installed. You can get them from 30 | \href{https://github.com/economist-components/component-typography}{here} 31 | } 32 | -------------------------------------------------------------------------------- /tests/tinytest.R: -------------------------------------------------------------------------------- 1 | 2 | if ( requireNamespace("tinytest", quietly=TRUE) ){ 3 | tinytest::test_package("ggeconodist") 4 | } 5 | 6 | --------------------------------------------------------------------------------