From d341f9fa43aa01392d2fcbd03d99565097dae59f Mon Sep 17 00:00:00 2001 From: hrbrmstr Date: Sat, 7 Mar 2015 12:41:34 -0500 Subject: [PATCH 1/2] x axis now supports continuous scale as well as date scale --- R/streamgraph.R | 56 +++++++++++++++++++++++---------- README.Rmd | 13 +++++--- inst/htmlwidgets/streamgraph.js | 29 ++++++++++++++--- man/sg_axis_x.Rd | 14 ++++++--- man/streamgraph.Rd | 6 ++-- tests/testthat/sg.R | 23 ++++++++++++-- 6 files changed, 108 insertions(+), 33 deletions(-) diff --git a/R/streamgraph.R b/R/streamgraph.R index ea0d87c..3e94821 100644 --- a/R/streamgraph.R +++ b/R/streamgraph.R @@ -23,6 +23,7 @@ #' \code{linear}, \code{step}, \code{step-before}, \code{step-after}, \code{basis}, \code{basis-open}, #' \code{cardinal-open}, \code{monotone} #' @param interactive set to \code{FALSE} if you do not want an interactive streamgraph +#' @param scale axis scale (\code{date} [default] or \code{continuous}) #' @param top top margin (default should be fine, this allows for fine-tuning plot space) #' @param right right margin (default should be fine, this allows for fine-tuning plot space) #' @param bottom bottom margin (default should be fine, this allows for fine-tuning plot space) @@ -52,6 +53,7 @@ streamgraph <- function(data, offset="silhouette", interpolate="cardinal", interactive=TRUE, + scale="date", top=20, right=40, bottom=30, @@ -77,14 +79,26 @@ streamgraph <- function(data, xtf <- "%b" xti <- 1 - if (all(class(data$date) %in% c("numeric", "character", "integer"))) { - if (all(nchar(as.character(data$date)) == 4)) { - data %>% - mutate(date=sprintf("%04d-01-01", as.numeric(date))) -> data - xtu <- "year" - xtf <- "%Y" - xti <- 10 + if (scale=="date") { + + # date format + + if (all(class(data$date) %in% c("numeric", "character", "integer"))) { + if (all(nchar(as.character(data$date)) == 4)) { + data %>% + mutate(date=sprintf("%04d-01-01", as.numeric(date))) -> data + xtu <- "year" + xtf <- "%Y" + xti <- 10 + } } + + } else { + + xtu <- NULL + xtf <- ",.0f" + xti <- 10 + } # needs all combos, so we do the equiv of expand.grid, but w/dplyr & tidyr @@ -94,11 +108,15 @@ streamgraph <- function(data, mutate(value=ifelse(is.na(value), 0, value)) %>% select(key, value, date) -> data - # date format + if (scale=="date") { - data %>% - mutate(date=format(as.Date(date), "%Y-%m-%d")) %>% - arrange(date) -> data + # date format + + data %>% + mutate(date=format(as.Date(date), "%Y-%m-%d")) %>% + arrange(date) -> data + + } params = list( data=data, @@ -120,7 +138,8 @@ streamgraph <- function(data, legend=FALSE, legend_label="", fill="brewer", - label_col="black" + label_col="black", + x_scale=scale ) htmlwidgets::createWidget( @@ -139,10 +158,15 @@ streamgraph <- function(data, #' streamgraph x axis. #' #' @param sg streamgraph object -#' @param tick_interval interval between ticks, not tick count (defaults to \code{10} if source data is in years, otherwise \code{1}) -#' @param tick_units unit the ticks are in; d3 time scale unit specifier (defaults to \code{month}) -#' @param tick_format how to show the labels (subset of \code{strftime} formatters) (defaults to \code{\%b}) -#' @param show show vertical gridlines? (defaults to \code{FALSE}) +#' @param ticks when \code{scale} is \code{date}, \code{ticks} is the interval +#' between ticks. when \code{scale} is \code{continuous}, \code{ticks} is +#' the total number of ticks (i.e. "tick count") [defaults to \code{10}] +#' @param tick_units unit the ticks are in; d3 time scale unit specifier +#' (defaults to \code{month} for \code{date} scale otherwise not used) +#' @param tick_format how to show the labels (subset of \code{strftime} +#' formatters for \code{date} scale, otherwise \code{sprintf} formats for +#' \code{continuous} scale) (defaults to \code{\%b} - must specify if \code{continuous}). +#' See \href{D3 formatting}{https://github.com/mbostock/d3/wiki/Formatting} for more details. #' @return streamgraph object #' @export #' @examples \dontrun{ diff --git a/README.Rmd b/README.Rmd index 2ee5570..a37761b 100644 --- a/README.Rmd +++ b/README.Rmd @@ -1,7 +1,7 @@ --- title: "README" author: "Bob Rudis" -date: February 16, 2015 +date: March 7, 2015 output: md_document: variant: markdown_github @@ -19,19 +19,24 @@ organic shape. Streamgraphs were developed by Lee Byron and popularized by their use in a February 2008 New York Times article on movie box office revenues. ([Wikipedia](http://en.wikipedia.org/wiki/Streamgraph)) +The x axis values can be continous or dates. + +### TODO + +- Support is planned for `xts` objects, but not for a bit. +- Support for categorical/discrete x axis + The following functions are implemented: - `streamgraph` : Create a new streamgraph - `sg_axis_x` : Modify streamgraph x axis formatting - `sg_axis_y` : Modify streamgraph y axis formatting - `sg_colors` : Modify streamgraph axis text, legend popup label text and tooltip text colors (NOTE: no longer modifies fill colors, use `sg_fill_*` for fill colors) -- `sg_legend` : Add select menu "legend" to interactive streamgraphs +- `sg_legend` : Add select menu "legend" to interactive streamgraphs - `sg_fill_brewer` : Specify a ColorBrewer palette to use for the stream fills - `sg_fill_manual` : Specify a manual color palette to use for the stream fills - `sg_fill_tableau` : Specify a Tableau color palette to use for the stream flls -Support is planned for `xts` objects, but not for a bit. - ### News - Version `0.1` released diff --git a/inst/htmlwidgets/streamgraph.js b/inst/htmlwidgets/streamgraph.js index 348929f..3c39486 100644 --- a/inst/htmlwidgets/streamgraph.js +++ b/inst/htmlwidgets/streamgraph.js @@ -1,3 +1,5 @@ +var dbg, dbg2; + HTMLWidgets.widget({ name: 'streamgraph', @@ -21,14 +23,22 @@ HTMLWidgets.widget({ var format = d3.time.format("%Y-%m-%d"); + dbg = params ; + // reformat the data var data = HTMLWidgets.dataframeToD3(params.data) ; data.forEach(function(d) { - d.date = format.parse(d.date); + if (params.x_scale == "date") { + d.date = format.parse(d.date); + } else { + d.date = +d.date; + } d.value = +d.value; }); + dbg2 = data + // assign colors var colorrange = []; @@ -52,7 +62,12 @@ HTMLWidgets.widget({ width = width - margin.left - margin.right; height = height - margin.top - margin.bottom; - var x = d3.time.scale().range([0, width]); + var x ; + if (params.x_scale == "date") { + x = d3.time.scale().range([0, width]); + } else { + x = d3.scale.linear().range([0, width]) ; + } var y = d3.scale.linear().range([height-10, 0]); var z = d3.scale.ordinal().range(colorrange) .domain(d3.set(data.map(function(d) { return(d.key) })).values().sort()); @@ -60,10 +75,16 @@ HTMLWidgets.widget({ var xAxis = d3.svg.axis().scale(x) .orient("bottom") - .ticks(d3.time[params.x_tick_units], params.x_tick_interval) - .tickFormat(d3.time.format(params.x_tick_format)) .tickPadding(8); + if (params.x_scale == "continuous") { + xAxis = xAxis.ticks(params.x_tick_interval) + .tickFormat(d3.format(params.x_tick_format)) + } else { + xAxis = xAxis.ticks(d3.time[params.x_tick_units], params.x_tick_interval) + .tickFormat(d3.time.format(params.x_tick_format)) + } + var yAxis = d3.svg.axis().scale(y) .ticks(params.y_tick_count) .tickFormat(d3.format(params.y_tick_format)) diff --git a/man/sg_axis_x.Rd b/man/sg_axis_x.Rd index 6df375e..8f8dbfc 100644 --- a/man/sg_axis_x.Rd +++ b/man/sg_axis_x.Rd @@ -9,13 +9,17 @@ sg_axis_x(sg, tick_interval = NULL, tick_units = NULL, tick_format = NULL) \arguments{ \item{sg}{streamgraph object} -\item{tick_interval}{interval between ticks, not tick count (defaults to \code{10} if source data is in years, otherwise \code{1})} +\item{tick_units}{unit the ticks are in; d3 time scale unit specifier +(defaults to \code{month} for \code{date} scale otherwise not used)} -\item{tick_units}{unit the ticks are in; d3 time scale unit specifier (defaults to \code{month})} +\item{tick_format}{how to show the labels (subset of \code{strftime} +formatters for \code{date} scale, otherwise \code{sprintf} formats for +\code{continuous} scale) (defaults to \code{\%b} - must specify if \code{continuous}). +See \href{D3 formatting}{https://github.com/mbostock/d3/wiki/Formatting} for more details.} -\item{tick_format}{how to show the labels (subset of \code{strftime} formatters) (defaults to \code{\%b})} - -\item{show}{show vertical gridlines? (defaults to \code{FALSE})} +\item{ticks}{when \code{scale} is \code{date}, \code{ticks} is the interval +between ticks. when \code{scale} is \code{continuous}, \code{ticks} is +the total number of ticks (i.e. "tick count") [defaults to \code{10}]} } \value{ streamgraph object diff --git a/man/streamgraph.Rd b/man/streamgraph.Rd index 9330479..6345bb8 100644 --- a/man/streamgraph.Rd +++ b/man/streamgraph.Rd @@ -6,8 +6,8 @@ \usage{ streamgraph(data, key = "key", value = "value", date = "date", width = NULL, height = NULL, offset = "silhouette", - interpolate = "cardinal", interactive = TRUE, top = 20, right = 40, - bottom = 30, left = 50) + interpolate = "cardinal", interactive = TRUE, scale = "date", + top = 20, right = 40, bottom = 30, left = 50) } \arguments{ \item{data}{data frame} @@ -33,6 +33,8 @@ The default is probably fine fore most uses, but can be one of \code{cardinal} ( \item{interactive}{set to \code{FALSE} if you do not want an interactive streamgraph} +\item{scale}{axis scale (\code{date} [default] or \code{continuous})} + \item{top}{top margin (default should be fine, this allows for fine-tuning plot space)} \item{right}{right margin (default should be fine, this allows for fine-tuning plot space)} diff --git a/tests/testthat/sg.R b/tests/testthat/sg.R index 640de01..84278c1 100644 --- a/tests/testthat/sg.R +++ b/tests/testthat/sg.R @@ -17,11 +17,11 @@ ggplot2::movies %>% streamgraph(dat, "genre", "n", "year", interactive=TRUE) %>% sg_axis_x(20, "year", "%Y") %>% - sg_colors("#1F77B4", "#1F77B4", "black") %>% + sg_colors(palette=NULL, "#1F77B4", "#1F77B4", "black") %>% sg_fill_tableau("tableau20") %>% # sg_fill_manual(c("red", "#00ff00", rgb(0,0,1))) %>% # sg_fill_brewer("Spectral") %>% - sg_legend(TRUE, "Genre") + sg_legend(TRUE, "Genre:") str(ggplot2::movies) @@ -73,3 +73,22 @@ streamgraph(dat, "name", "n", "year") %>% babynames[babynames$name %in% dat1$name,] + +dat <- read.table(text="week variable value + 40 rev1 372.096 + 40 rev2 506.880 + 40 rev3 1411.200 + 40 rev4 198.528 + 40 rev5 60.800 + 43 rev1 342.912 + 43 rev2 501.120 + 43 rev3 132.352 + 43 rev4 267.712 + 43 rev5 82.368 + 44 rev1 357.504 + 44 rev2 466.560", header=TRUE) + +dat %>% streamgraph("variable","value","week", scale="continuous") %>% sg_axis_x(tick_format="d") + + + From d6136dd25e71470168ae8b09ae7e3b9fb8d9ca56 Mon Sep 17 00:00:00 2001 From: hrbrmstr Date: Sat, 7 Mar 2015 12:46:10 -0500 Subject: [PATCH 2/2] update README --- README.Rmd | 1 + README.md | 12 +++++++++--- 2 files changed, 10 insertions(+), 3 deletions(-) diff --git a/README.Rmd b/README.Rmd index a37761b..dd95d66 100644 --- a/README.Rmd +++ b/README.Rmd @@ -50,6 +50,7 @@ The following functions are implemented: - Versioin `0.4.2` released - fixed bug (thanks to teammate @bhaskarvk) that causes inconsistent color rendering for each area component (noticeable on resize of flexible width/height graphs) - Version `0.5` released - deprecated use of `sg_colors`. Its functionality will change soon and is replaced by three `sg_fill_*` functions (`brewer`, `manual` and `tableau`) which makes more sense, is aligned to the `ggplot2` way of specifying fill aesthetics and now makes it easier to highly customize the streamgraph appearance. - Version `0.5.1` released - `sg_colors` now has nothing to do with the stream fills but _does_ set the axis text, legend popup label text and tooltip text. +- Version `0.6` released - New `scale` parameter to `streamgraph` lets you choose between continuous or date scales. ### Installation diff --git a/README.md b/README.md index 9770eca..33f059a 100644 --- a/README.md +++ b/README.md @@ -6,6 +6,13 @@ streamgraph is an htmlwidget for making streamgraphs. A streamgraph (or "stream graph") is a type of stacked area graph which is displaced around a central axis, resulting in a flowing, organic shape. Streamgraphs were developed by Lee Byron and popularized by their use in a February 2008 New York Times article on movie box office revenues. ([Wikipedia](http://en.wikipedia.org/wiki/Streamgraph)) +The x axis values can be continous or dates. + +### TODO + +- Support is planned for `xts` objects, but not for a bit. +- Support for categorical/discrete x axis + The following functions are implemented: - `streamgraph` : Create a new streamgraph @@ -17,8 +24,6 @@ The following functions are implemented: - `sg_fill_manual` : Specify a manual color palette to use for the stream fills - `sg_fill_tableau` : Specify a Tableau color palette to use for the stream flls -Support is planned for `xts` objects, but not for a bit. - ### News - Version `0.1` released @@ -32,6 +37,7 @@ Support is planned for `xts` objects, but not for a bit. - Versioin `0.4.2` released - fixed bug (thanks to teammate @bhaskarvk) that causes inconsistent color rendering for each area component (noticeable on resize of flexible width/height graphs) - Version `0.5` released - deprecated use of `sg_colors`. Its functionality will change soon and is replaced by three `sg_fill_*` functions (`brewer`, `manual` and `tableau`) which makes more sense, is aligned to the `ggplot2` way of specifying fill aesthetics and now makes it easier to highly customize the streamgraph appearance. - Version `0.5.1` released - `sg_colors` now has nothing to do with the stream fills but *does* set the axis text, legend popup label text and tooltip text. +- Version `0.6` released - New `scale` parameter to `streamgraph` lets you choose between continuous or date scales. ### Installation @@ -76,7 +82,7 @@ library(testthat) date() ``` - ## [1] "Mon Feb 16 19:46:47 2015" + ## [1] "Sat Mar 7 12:45:54 2015" ``` r test_dir("tests/")