diff --git a/NAMESPACE b/NAMESPACE index 5ac78f4..186dd4f 100644 --- a/NAMESPACE +++ b/NAMESPACE @@ -16,6 +16,7 @@ export(pal_locuszoom) export(pal_material) export(pal_nejm) export(pal_npg) +export(pal_observable) export(pal_rickandmorty) export(pal_simpsons) export(pal_startrek) @@ -40,6 +41,7 @@ export(scale_color_locuszoom) export(scale_color_material) export(scale_color_nejm) export(scale_color_npg) +export(scale_color_observable) export(scale_color_rickandmorty) export(scale_color_simpsons) export(scale_color_startrek) @@ -62,6 +64,7 @@ export(scale_colour_locuszoom) export(scale_colour_material) export(scale_colour_nejm) export(scale_colour_npg) +export(scale_colour_observable) export(scale_colour_rickandmorty) export(scale_colour_simpsons) export(scale_colour_startrek) @@ -84,6 +87,7 @@ export(scale_fill_locuszoom) export(scale_fill_material) export(scale_fill_nejm) export(scale_fill_npg) +export(scale_fill_observable) export(scale_fill_rickandmorty) export(scale_fill_simpsons) export(scale_fill_startrek) diff --git a/NEWS.md b/NEWS.md index e2168dd..5da2bfe 100644 --- a/NEWS.md +++ b/NEWS.md @@ -1,5 +1,10 @@ # ggsci 3.1.0.9000 +## New features + +- Add the Observable 10 palette in `scale_color_observable()` + and `scale_fill_observable()` (#41). + ## Improvements - Move internal color palette data from `R/sysdata.rda` to `R/palettes.R`. diff --git a/R/discrete-observable.R b/R/discrete-observable.R new file mode 100644 index 0000000..c2d74a0 --- /dev/null +++ b/R/discrete-observable.R @@ -0,0 +1,104 @@ +#' Observable 10 color palette +#' +#' The Observable 10 palette. +#' +#' @param palette Palette type. +#' Currently there is one available option: `"observable10"` +#' (10-color palette). +#' @param alpha Transparency level, a real number in (0, 1]. +#' See `alpha` in [grDevices::rgb()] for details. +#' +#' @export pal_observable +#' +#' @importFrom grDevices col2rgb rgb +#' @importFrom scales manual_pal +#' +#' @author Nan Xiao | \email{me@nanx.me} | +#' +#' @references +#' Pettiross J (2023). "Crafting data colors and staying on brand." +#' _Observable blog_. +#' +#' @examples +#' library("scales") +#' show_col(pal_observable("observable10")(10)) +#' show_col(pal_observable("observable10", alpha = 0.6)(10)) +pal_observable <- function(palette = c("observable10"), alpha = 1) { + palette <- match.arg(palette) + + if (alpha > 1L || alpha <= 0L) stop("alpha must be in (0, 1]") + + raw_cols <- ggsci_db$"observable"[[palette]] + raw_cols_rgb <- col2rgb(raw_cols) + alpha_cols <- rgb( + raw_cols_rgb[1L, ], raw_cols_rgb[2L, ], raw_cols_rgb[3L, ], + alpha = alpha * 255L, names = names(raw_cols), + maxColorValue = 255L + ) + + manual_pal(unname(alpha_cols)) +} + +#' Observable 10 color scales +#' +#' See [pal_observable()] for details. +#' +#' @inheritParams pal_observable +#' @param ... Additional parameters for [ggplot2::discrete_scale()]. +#' +#' @export scale_color_observable +#' +#' @importFrom ggplot2 discrete_scale +#' +#' @author Nan Xiao | \email{me@nanx.me} | +#' +#' @references +#' Pettiross J (2023). "Crafting data colors and staying on brand." +#' _Observable blog_. +#' +#' @rdname scale_observable +#' +#' @examples +#' library("ggplot2") +#' data("diamonds") +#' +#' ggplot( +#' subset(diamonds, carat >= 2.2), +#' aes(x = table, y = price, colour = cut) +#' ) + +#' geom_point(alpha = 0.7) + +#' geom_smooth(method = "loess", alpha = 0.1, size = 1, span = 1) + +#' theme_bw() + +#' scale_color_observable() +#' +#' ggplot( +#' subset(diamonds, carat > 2.2 & depth > 55 & depth < 70), +#' aes(x = depth, fill = cut) +#' ) + +#' geom_histogram(colour = "black", binwidth = 1, position = "dodge") + +#' theme_bw() + +#' scale_fill_observable() +scale_color_observable <- function(palette = c("observable10"), alpha = 1, ...) { + palette <- match.arg(palette) + if (is_ggplot2_350()) { + discrete_scale("colour", palette = pal_observable(palette, alpha), ...) + } else { + discrete_scale("colour", scale_name = "observable", palette = pal_observable(palette, alpha), ...) + } +} + +#' @export scale_colour_observable +#' @rdname scale_observable +scale_colour_observable <- scale_color_observable + +#' @export scale_fill_observable +#' @importFrom ggplot2 discrete_scale +#' @rdname scale_observable +scale_fill_observable <- function(palette = c("observable10"), alpha = 1, ...) { + palette <- match.arg(palette) + if (is_ggplot2_350()) { + discrete_scale("fill", palette = pal_observable(palette, alpha), ...) + } else { + discrete_scale("fill", scale_name = "observable", palette = pal_observable(palette, alpha), ...) + } +} diff --git a/R/palettes.R b/R/palettes.R index f6dafdc..239334c 100644 --- a/R/palettes.R +++ b/R/palettes.R @@ -137,6 +137,20 @@ ggsci_db$"d3"$"category20c" <- c( "Snuff" = "#DADAEB", "Alto" = "#D9D9D9" ) +# Observable 10 color palette +ggsci_db$"observable"$"observable10" <- c( + "Blue" = "#4269D0", + "Orange" = "#EFB118", + "Red" = "#FF725C", + "Cyan" = "#6CC5B0", + "Green" = "#3CA951", + "Pink" = "#FF8AB7", + "Purple" = "#A463F2", + "LightBlue" = "#97BBF5", + "Brown" = "#9C6B4E", + "Gray" = "#9498A0" +) + # Color palette inspired by IGV ggsci_db$"igv"$"default" <- c( "chr1" = "#5050FF", "chr2" = "#CE3D32", "chr3" = "#749B58", diff --git a/README.Rmd b/README.Rmd index e22c62b..56d9087 100644 --- a/README.Rmd +++ b/README.Rmd @@ -158,6 +158,14 @@ p2_d3 <- p2 + scale_fill_d3() grid.arrange(p1_d3, p2_d3, ncol = 2) ``` +### Observable + +```{r, ggsci-observable} +p1_observable <- p1 + scale_color_observable() +p2_observable <- p2 + scale_fill_observable() +grid.arrange(p1_observable, p2_observable, ncol = 2) +``` + ### LocusZoom ```{r, ggsci-locuszoom} diff --git a/README.md b/README.md index 16ad466..af86b1a 100644 --- a/README.md +++ b/README.md @@ -71,6 +71,10 @@ open with `vignette("ggsci")` in R) for a quick-start guide. +### Observable + + + ### LocusZoom diff --git a/_pkgdown.yml b/_pkgdown.yml index 21cdd62..250a370 100644 --- a/_pkgdown.yml +++ b/_pkgdown.yml @@ -60,6 +60,12 @@ reference: - scale_color_d3 - scale_colour_d3 - scale_fill_d3 + - title: "Observable" + contents: + - pal_observable + - scale_color_observable + - scale_colour_observable + - scale_fill_observable - title: "LocusZoom" contents: - pal_locuszoom diff --git a/man/figures/README-ggsci-observable-1.png b/man/figures/README-ggsci-observable-1.png new file mode 100644 index 0000000..2ef0b8d Binary files /dev/null and b/man/figures/README-ggsci-observable-1.png differ diff --git a/man/pal_observable.Rd b/man/pal_observable.Rd new file mode 100644 index 0000000..f31fbb9 --- /dev/null +++ b/man/pal_observable.Rd @@ -0,0 +1,31 @@ +% Generated by roxygen2: do not edit by hand +% Please edit documentation in R/discrete-observable.R +\name{pal_observable} +\alias{pal_observable} +\title{Observable 10 color palette} +\usage{ +pal_observable(palette = c("observable10"), alpha = 1) +} +\arguments{ +\item{palette}{Palette type. +Currently there is one available option: \code{"observable10"} +(10-color palette).} + +\item{alpha}{Transparency level, a real number in (0, 1]. +See \code{alpha} in \code{\link[grDevices:rgb]{grDevices::rgb()}} for details.} +} +\description{ +The Observable 10 palette. +} +\examples{ +library("scales") +show_col(pal_observable("observable10")(10)) +show_col(pal_observable("observable10", alpha = 0.6)(10)) +} +\references{ +Pettiross J (2023). "Crafting data colors and staying on brand." +\emph{Observable blog}. \url{https://observablehq.com/blog/crafting-data-colors} +} +\author{ +Nan Xiao | \email{me@nanx.me} | \url{https://nanx.me} +} diff --git a/man/scale_observable.Rd b/man/scale_observable.Rd new file mode 100644 index 0000000..40c67fc --- /dev/null +++ b/man/scale_observable.Rd @@ -0,0 +1,55 @@ +% Generated by roxygen2: do not edit by hand +% Please edit documentation in R/discrete-observable.R +\name{scale_color_observable} +\alias{scale_color_observable} +\alias{scale_colour_observable} +\alias{scale_fill_observable} +\title{Observable 10 color scales} +\usage{ +scale_color_observable(palette = c("observable10"), alpha = 1, ...) + +scale_colour_observable(palette = c("observable10"), alpha = 1, ...) + +scale_fill_observable(palette = c("observable10"), alpha = 1, ...) +} +\arguments{ +\item{palette}{Palette type. +Currently there is one available option: \code{"observable10"} +(10-color palette).} + +\item{alpha}{Transparency level, a real number in (0, 1]. +See \code{alpha} in \code{\link[grDevices:rgb]{grDevices::rgb()}} for details.} + +\item{...}{Additional parameters for \code{\link[ggplot2:discrete_scale]{ggplot2::discrete_scale()}}.} +} +\description{ +See \code{\link[=pal_observable]{pal_observable()}} for details. +} +\examples{ +library("ggplot2") +data("diamonds") + +ggplot( + subset(diamonds, carat >= 2.2), + aes(x = table, y = price, colour = cut) +) + + geom_point(alpha = 0.7) + + geom_smooth(method = "loess", alpha = 0.1, size = 1, span = 1) + + theme_bw() + + scale_color_observable() + +ggplot( + subset(diamonds, carat > 2.2 & depth > 55 & depth < 70), + aes(x = depth, fill = cut) +) + + geom_histogram(colour = "black", binwidth = 1, position = "dodge") + + theme_bw() + + scale_fill_observable() +} +\references{ +Pettiross J (2023). "Crafting data colors and staying on brand." +\emph{Observable blog}. \url{https://observablehq.com/blog/crafting-data-colors} +} +\author{ +Nan Xiao | \email{me@nanx.me} | \url{https://nanx.me} +} diff --git a/vignettes/ggsci.Rmd b/vignettes/ggsci.Rmd index e3dec61..fa2f9dc 100644 --- a/vignettes/ggsci.Rmd +++ b/vignettes/ggsci.Rmd @@ -84,6 +84,9 @@ summarized in the table below. | | | `"category20b"` | | | | | `"category20c"` | | +-----------------+------------------------------+--------------------------------+----------------------+ +| Observable | `scale_color_observable()` | `"observable10"` | `pal_observable()` | +| | `scale_fill_observable()` | | | ++-----------------+------------------------------+--------------------------------+----------------------+ | LocusZoom | `scale_color_locuszoom()` | `"default"` | `pal_locuszoom()` | | | `scale_fill_locuszoom()` | | | +-----------------+------------------------------+--------------------------------+----------------------+ @@ -266,6 +269,17 @@ p2_d3 <- p2 + scale_fill_d3() grid.arrange(p1_d3, p2_d3, ncol = 2) ``` +### Observable + +The [Observable 10 palette](https://observablehq.com/blog/crafting-data-colors) +is the default categorical colors scheme used by Observable. + +```{r} +p1_observable <- p1 + scale_color_observable() +p2_observable <- p2 + scale_fill_observable() +grid.arrange(p1_observable, p2_observable, ncol = 2) +``` + ### LocusZoom The LocusZoom palette is based on the colors used by