diff --git a/DESCRIPTION b/DESCRIPTION index 94576a3885..f723c9b9bb 100644 --- a/DESCRIPTION +++ b/DESCRIPTION @@ -22,7 +22,7 @@ Imports: MASS, plyr (>= 1.7.1), reshape2, - scales (>= 0.3.0), + scales (>= 0.4.0.9002), stats, tibble, lazyeval @@ -44,6 +44,8 @@ Suggests: rpart, rmarkdown, svglite +Remotes: + hadley/scales Enhances: sp License: GPL-2 | file LICENSE URL: http://ggplot2.org, https://github.com/hadley/ggplot2 diff --git a/NAMESPACE b/NAMESPACE index 81c5bfa65d..c4be3f5142 100644 --- a/NAMESPACE +++ b/NAMESPACE @@ -83,6 +83,7 @@ S3method(scale_type,POSIXt) S3method(scale_type,character) S3method(scale_type,default) S3method(scale_type,factor) +S3method(scale_type,hms) S3method(scale_type,logical) S3method(scale_type,numeric) S3method(scale_type,ordered) @@ -420,6 +421,7 @@ export(scale_x_discrete) export(scale_x_log10) export(scale_x_reverse) export(scale_x_sqrt) +export(scale_x_time) export(scale_y_continuous) export(scale_y_date) export(scale_y_datetime) @@ -427,6 +429,7 @@ export(scale_y_discrete) export(scale_y_log10) export(scale_y_reverse) export(scale_y_sqrt) +export(scale_y_time) export(sec_axis) export(should_stop) export(stat_bin) diff --git a/NEWS.md b/NEWS.md index dfe47d578c..08ed0527b4 100644 --- a/NEWS.md +++ b/NEWS.md @@ -1,5 +1,8 @@ # ggplot2 2.1.0.9000 +* Added scales `scale_x_time()` and `scale_y_time()` which are applied + automatically when you plot objects of type hms (#1752). + * `layer()` gains new `check.aes` and `check.param` arguments. These allow geom/stat authors to optional suppress checks for known aesthetics/parameters. Currently this is used only in `geom_blank()` which powers `expand_limits()` diff --git a/R/scale-date.r b/R/scale-date.r index 9894e4a579..0d45eb32e0 100644 --- a/R/scale-date.r +++ b/R/scale-date.r @@ -1,10 +1,13 @@ -#' Position scale, date & date times +#' Positions scale for date/times #' -#' Use \code{scale_*_date} with \code{Date} variables, and -#' \code{scale_*_datetime} with \code{POSIXct} variables. +#' Use +#' \code{scale_*_date} for dates (class \code{Date}), +#' \code{scale_*_datetime} for datetimes (class \code{POSIXct}), and +#' \code{scale_*_time} for times (class \code{hms}). #' #' @name scale_date #' @inheritParams continuous_scale +#' @inheritParams scale_x_continuous #' @param date_breaks A string giving the distance between breaks like "2 #' weeks", or "10 years". If both \code{breaks} and \code{date_breaks} are #' specified, \code{date_breaks} wins. @@ -71,7 +74,6 @@ scale_y_date <- function(name = waiver(), ) } - #' @export #' @rdname scale_date scale_x_datetime <- function(name = waiver(), @@ -109,6 +111,61 @@ scale_y_datetime <- function(name = waiver(), ) } + + +#' @export +#' @rdname scale_date +scale_x_time <- function(name = waiver(), + breaks = waiver(), + minor_breaks = waiver(), + labels = waiver(), + limits = NULL, + expand = waiver(), + oob = censor, + na.value = NA_real_, + position = "bottom") { + + scale_x_continuous( + name = name, + breaks = breaks, + labels = labels, + minor_breaks = minor_breaks, + limits = limits, + expand = expand, + oob = oob, + na.value = na.value, + position = position, + trans = scales::hms_trans() + ) +} + + +#' @rdname scale_date +#' @export +scale_y_time <- function(name = waiver(), + breaks = waiver(), + minor_breaks = waiver(), + labels = waiver(), + limits = NULL, + expand = waiver(), + oob = censor, + na.value = NA_real_, + position = "left") { + + scale_y_continuous( + name = name, + breaks = breaks, + labels = labels, + minor_breaks = minor_breaks, + limits = limits, + expand = expand, + oob = oob, + na.value = na.value, + position = position, + trans = scales::hms_trans() + ) +} + scale_datetime <- function(aesthetics, trans, breaks = pretty_breaks(), minor_breaks = waiver(), labels = waiver(), date_breaks = waiver(), @@ -116,7 +173,6 @@ scale_datetime <- function(aesthetics, trans, date_minor_breaks = waiver(), timezone = NULL, ...) { - name <- switch(trans, date = "date", time = "datetime") # Backward compatibility if (is.character(breaks)) breaks <- date_breaks(breaks) @@ -135,10 +191,19 @@ scale_datetime <- function(aesthetics, trans, } } - scale_class <- switch(trans, date = ScaleContinuousDate, time = ScaleContinuousDatetime) - sc <- continuous_scale(aesthetics, name, identity, + name <- switch(trans, + date = "date", + time = "datetime" + ) + scale_class <- switch(trans, + date = ScaleContinuousDate, + time = ScaleContinuousDatetime + ) + sc <- continuous_scale( + aesthetics, name, identity, breaks = breaks, minor_breaks = minor_breaks, labels = labels, - guide = "none", trans = trans, ..., super = scale_class) + guide = "none", trans = trans, ..., super = scale_class + ) sc$timezone <- timezone sc } diff --git a/R/scale-type.R b/R/scale-type.R index b08b1f973b..f6583f7396 100644 --- a/R/scale-type.R +++ b/R/scale-type.R @@ -64,3 +64,6 @@ scale_type.Date <- function(x) c("date", "continuous") #' @export scale_type.numeric <- function(x) "continuous" + +#' @export +scale_type.hms <- function(x) "time" diff --git a/man/scale_date.Rd b/man/scale_date.Rd index 1f00018a64..64a0235a14 100644 --- a/man/scale_date.Rd +++ b/man/scale_date.Rd @@ -4,9 +4,11 @@ \alias{scale_date} \alias{scale_x_date} \alias{scale_x_datetime} +\alias{scale_x_time} \alias{scale_y_date} \alias{scale_y_datetime} -\title{Position scale, date & date times} +\alias{scale_y_time} +\title{Positions scale for date/times} \usage{ scale_x_date(name = waiver(), breaks = waiver(), date_breaks = waiver(), labels = waiver(), date_labels = waiver(), minor_breaks = waiver(), @@ -27,6 +29,14 @@ scale_y_datetime(name = waiver(), breaks = waiver(), date_breaks = waiver(), labels = waiver(), date_labels = waiver(), minor_breaks = waiver(), date_minor_breaks = waiver(), timezone = NULL, limits = NULL, expand = waiver(), position = "left") + +scale_x_time(name = waiver(), breaks = waiver(), minor_breaks = waiver(), + labels = waiver(), limits = NULL, expand = waiver(), oob = censor, + na.value = NA_real_, position = "bottom") + +scale_y_time(name = waiver(), breaks = waiver(), minor_breaks = waiver(), + labels = waiver(), limits = NULL, expand = waiver(), oob = censor, + na.value = NA_real_, position = "left") } \arguments{ \item{name}{The name of the scale. Used as axis or legend title. If @@ -85,10 +95,17 @@ scales, "top" or "bottom" for horizontal scales} \item{timezone}{The timezone to use for display on the axes. The default (\code{NULL}) uses the timezone encoded in the data.} + +\item{oob}{Function that handles limits outside of the scale limits +(out of bounds). The default replaces out of bounds values with NA.} + +\item{na.value}{Missing values will be replaced with this value.} } \description{ -Use \code{scale_*_date} with \code{Date} variables, and -\code{scale_*_datetime} with \code{POSIXct} variables. +Use +\code{scale_*_date} for dates (class \code{Date}), +\code{scale_*_datetime} for datetimes (class \code{POSIXct}), and +\code{scale_*_time} for times (class \code{hms}). } \examples{ last_month <- Sys.Date() - 0:29