diff --git a/content/blog/scales-1-4-0/figs/unnamed-chunk-2-1.png b/content/blog/scales-1-4-0/figs/unnamed-chunk-2-1.png new file mode 100644 index 00000000..3a00cb5a Binary files /dev/null and b/content/blog/scales-1-4-0/figs/unnamed-chunk-2-1.png differ diff --git a/content/blog/scales-1-4-0/figs/unnamed-chunk-5-1.png b/content/blog/scales-1-4-0/figs/unnamed-chunk-5-1.png new file mode 100644 index 00000000..682ee2d7 Binary files /dev/null and b/content/blog/scales-1-4-0/figs/unnamed-chunk-5-1.png differ diff --git a/content/blog/scales-1-4-0/figs/unnamed-chunk-6-1.png b/content/blog/scales-1-4-0/figs/unnamed-chunk-6-1.png new file mode 100644 index 00000000..38f8c2b3 Binary files /dev/null and b/content/blog/scales-1-4-0/figs/unnamed-chunk-6-1.png differ diff --git a/content/blog/scales-1-4-0/figs/unnamed-chunk-7-1.png b/content/blog/scales-1-4-0/figs/unnamed-chunk-7-1.png new file mode 100644 index 00000000..3204326b Binary files /dev/null and b/content/blog/scales-1-4-0/figs/unnamed-chunk-7-1.png differ diff --git a/content/blog/scales-1-4-0/index.Rmd b/content/blog/scales-1-4-0/index.Rmd new file mode 100644 index 00000000..a8d257db --- /dev/null +++ b/content/blog/scales-1-4-0/index.Rmd @@ -0,0 +1,184 @@ +--- +output: hugodown::hugo_document + +slug: scales-1-4-0 +title: scales 1.4.0 +date: 2024-10-30 +author: Teun van den Brand +description: > + The new 1.4.0 release of the scales package adds some colourful updates. + Read about colour manipulation, palettes and new label functions. + +photo: + url: https://unsplash.com/photos/a-close-up-of-a-person-holding-a-paintbrush-Xrelr7cTYm4 + author: Jennie Razumnaya + +# one of: "deep-dive", "learn", "package", "programming", "roundup", or "other" +categories: [package] +tags: [scales] +--- + + + +We're stoked to announce the release of [scales]({https://scales.r-lib.org/}) 1.4.0. +scales is a package that provides much of the scaling logic that is used in ggplot2 to a general framework, along with utility functions for e.g. formatting labels or creating colour palettes. + +You can install it from CRAN with: + +```{r, eval = FALSE} +install.packages("scales") +``` + +This blog post will give an overview of the 1.4.0 release, which has some nifty upgrades for working with colours and labels. + +You can see a full list of changes in the [release notes](https://scales.r-lib.org/news/index.html) + +```{r setup} +library(scales) +``` + +```{r ragg, include=FALSE} +knitr::opts_chunk$set(dev = "ragg_png") +``` + +## Colour manipulation + +The `alpha()` and `muted()` functions have been part of scales for a long time. +Back in the 1.1.0 release we swapped to [farver](https://farver.data-imaginist.com/) to power these functions. +We felt it was appropriate to use this package for other common colour tasks, and so `col_shift()`, `col_lighter()`, `col_darker()`, `col_saturate()` and `col_mix()` were born. + +```{r} +my_colours <- c("red", "green", "blue") + +m <- rbind( + original = my_colours, + shift = col_shift(my_colours, 90), + lighter = col_lighter(my_colours, 20), + darker = col_darker(my_colours, 20), + duller = col_saturate(my_colours, -50), + mixed = col_mix(my_colours, "orchid") +) + +show_col(t(m), ncol = ncol(m)) +text(x = ncol(m) + 0.25, y = -(1:nrow(m)) + 0.5, rownames(m), adj = 0) +``` + +## Palettes + +Palettes have also been reworked in this release to include some useful properties. +Palettes now come in one of two classes: 'pal_discrete' or 'pal_continuous'. + +```{r} +my_palette <- manual_pal(c("palegreen", "deepskyblue", "magenta")) +class(my_palette) +``` + +Having palettes as a class rather than as plain functions, allows us to store useful metadata about the palette which can be used downstream. +In addition, most colour palette functions also allow the aforementioned colour manipulation functions to work on the palette output. + +```{r} +palette_type(my_palette) + +palette_nlevels(my_palette) + +col_shift(my_palette, 180)(3) +``` + +With the new setup it is now possible to expand discrete palettes to continuous palettes with `as_continuous_pal()` or vise versa to chop up continuous palettes into discrete palettes with `as_discrete_pal()`. + +```{r} +plot(as_continuous_pal(my_palette)) +``` + +Another quality of life improvement for palettes, is that the 'scales' package now keeps track of named palettes. +By default, the collection of 'known' palettes is pre-populated with colour palettes from the grDevices, RColorBrewer and viridisLite packages. + + +```{r} +head(palette_names()) + +get_palette("Okabe-Ito")(8) +``` + +If you're a developer of a palette package, you can use `set_palette()` to register your palette. +This has the advantage that your palette is now available to users by name, which at times might be more convenient than having to call the palette generator function. +In the future, we plan to make it easier to work with named palettes in ggplot2. +Hopefully this will mean that mirroring every palette in a `scale_*()` function becomes obsolete. + +```{r, error=TRUE} +get_palette("aurora") + +set_palette("aurora", my_palette) +plot(get_palette("aurora")) +``` + +## Labels + +This release also provides improvements to labelling in the form of two new labelling functions and two new convenience functions for labels. +In contrast to most of scales' label functions, these label functions are great for discrete input. +First up is `label_glue()`, which uses the string interpolation from the glue package to format your labels. + +```{r} +label_glue("The {x} penguin")(c("Gentoo", "Chinstrap", "Adelie")) +``` + +The other labelling function, `label_dictionary()`, is convenient when some variable you use consists of short-codes or abbreviations. +You can provide `label_dictionary()` with a named vector that translates the values to prettier labels. +If one or more of your values doesn't exist in the dictionary, they stay as-is by default. + +```{r} +dict <- c( + diy = "Do it yourself", eta = "Estimated time of arrival", + asap = "As soon as possible", tldr = "Too long; didn't read" +) +label_dictionary(dict)(c("diy", "tldr", "bff")) +``` + +`compose_label()` is a useful convenience function we've added which will help you to create custom labelling behaviour without needing to write a labelling function from scratch. +Similar to `compose_trans()`, it allows you to chain together different labelling functions. + +```{r} +screaming_flowers <- compose_label(label_glue("The {x} flower"), toupper) +screaming_flowers(c("daffodil", "orchid", "tulip")) +``` +Lastly, we haven't completely forgotton about numeric labels either. +We have introduced the `number_options()` functions to globally populate defaults for functions such as `label_number()` and `label_currency()`. +This can be convenient if you produce statistical reports in non-English languages. + +```{r} +number_options( + decimal.mark = ",", + big.mark = ".", + style_negative = "minus", + currency.prefix = "", + currency.suffix = "€", + currency.decimal.mark = ",", + currency.big.mark = " ", + ordinal.rules = ordinal_french() +) + +label_currency(accuracy = 0.01)(c(0.1, 10, 1000000, -1000)) + +label_ordinal()(1:4) +``` + + + +## Acknowledgements + +We'd like to thank all people who have contributed in some way, whether it was filing issues, participating in discussion or contributing to code and documentation: + +[@Aariq](https://github.com/Aariq), [@Aehmlo](https://github.com/Aehmlo), [@Ali-Hudson](https://github.com/Ali-Hudson), [@cb12991](https://github.com/cb12991), [@colindouglas](https://github.com/colindouglas), [@d-morrison](https://github.com/d-morrison), [@davidhodge931](https://github.com/davidhodge931), [@EricMarcon](https://github.com/EricMarcon), [@kellijohnson-NOAA](https://github.com/kellijohnson-NOAA), [@kmcd39](https://github.com/kmcd39), [@lz1nwm](https://github.com/lz1nwm), [@mine-cetinkaya-rundel](https://github.com/mine-cetinkaya-rundel), [@mjskay](https://github.com/mjskay), [@Moohan](https://github.com/Moohan), [@muschellij2](https://github.com/muschellij2), [@ppreshant](https://github.com/ppreshant), [@rawktheuniversemon](https://github.com/rawktheuniversemon), [@rogiersbart](https://github.com/rogiersbart), [@SchmidtPaul](https://github.com/SchmidtPaul), [@teunbrand](https://github.com/teunbrand), and [@thomasp85](https://github.com/thomasp85). + + diff --git a/content/blog/scales-1-4-0/index.md b/content/blog/scales-1-4-0/index.md new file mode 100644 index 00000000..ac202454 --- /dev/null +++ b/content/blog/scales-1-4-0/index.md @@ -0,0 +1,219 @@ +--- +output: hugodown::hugo_document + +slug: scales-1-4-0 +title: scales 1.4.0 +date: 2024-10-30 +author: Teun van den Brand +description: > + The new 1.4.0 release of the scales package adds some colourful updates. + Read about colour manipulation, palettes and new label functions. + +photo: + url: https://unsplash.com/photos/a-close-up-of-a-person-holding-a-paintbrush-Xrelr7cTYm4 + author: Jennie Razumnaya + +# one of: "deep-dive", "learn", "package", "programming", "roundup", or "other" +categories: [package] +tags: [scales] +rmd_hash: 31a31e8ee7f5311f + +--- + + + +We're stoked to announce the release of [scales](%7Bhttps://scales.r-lib.org/%7D) 1.4.0. scales is a package that provides much of the scaling logic that is used in ggplot2 to a general framework, along with utility functions for e.g. formatting labels or creating colour palettes. + +You can install it from CRAN with: + +
install.packages("scales")
+
+my_colours <- c("red", "green", "blue")
+
+m <- rbind(
+ original = my_colours,
+ shift = col_shift(my_colours, 90),
+ lighter = col_lighter(my_colours, 20),
+ darker = col_darker(my_colours, 20),
+ duller = col_saturate(my_colours, -50),
+ mixed = col_mix(my_colours, "orchid")
+)
+
+show_col(t(m), ncol = ncol(m))
+text(x = ncol(m) + 0.25, y = -(1:nrow(m)) + 0.5, rownames(m), adj = 0)
+
+
+
+my_palette <- manual_pal(c("palegreen", "deepskyblue", "magenta"))
+class(my_palette)
+#> [1] "pal_discrete" "scales_pal" "function"
+
+
+palette_type(my_palette)
+#> [1] "colour"
+
+palette_nlevels(my_palette)
+#> [1] 3
+
+col_shift(my_palette, 180)(3)
+#> [1] "#FFC3FF" "#E4A735" "#00B100"
+
+
+plot(as_continuous_pal(my_palette))
+
+
+
+head(palette_names())
+#> [1] "greens 2" "r4" "greens 3" "blues" "terrain"
+#> [6] "tableau 10"
+
+get_palette("Okabe-Ito")(8)
+#> [1] "#000000" "#E69F00" "#56B4E9" "#009E73" "#F0E442" "#0072B2" "#D55E00"
+#> [8] "#CC79A7"
+
+
+get_palette("aurora")
+#> Error in `get_palette()`:
+#> ! Unknown palette: aurora
+
+set_palette("aurora", my_palette)
+plot(get_palette("aurora"))
+
+
+
+label_glue("The {x} penguin")(c("Gentoo", "Chinstrap", "Adelie"))
+#> The Gentoo penguin
+#> The Chinstrap penguin
+#> The Adelie penguin
+
+
+dict <- c(
+ diy = "Do it yourself", eta = "Estimated time of arrival",
+ asap = "As soon as possible", tldr = "Too long; didn't read"
+)
+label_dictionary(dict)(c("diy", "tldr", "bff"))
+#> [1] "Do it yourself" "Too long; didn't read" "bff"
+
+
+screaming_flowers <- compose_label(label_glue("The {x} flower"), toupper)
+screaming_flowers(c("daffodil", "orchid", "tulip"))
+#> THE DAFFODIL FLOWER
+#> THE ORCHID FLOWER
+#> THE TULIP FLOWER
+
+
+number_options(
+ decimal.mark = ",",
+ big.mark = ".",
+ style_negative = "minus",
+ currency.prefix = "",
+ currency.suffix = "€",
+ currency.decimal.mark = ",",
+ currency.big.mark = " ",
+ ordinal.rules = ordinal_french()
+)
+
+label_currency(accuracy = 0.01)(c(0.1, 10, 1000000, -1000))
+#> [1] "0,10€" "10,00€" "1 000 000,00€" "-1 000,00€"
+
+label_ordinal()(1:4)
+#> [1] "1er" "2e" "3e" "4e"
+
+
+