diff --git a/DESCRIPTION b/DESCRIPTION index 0dd2081..e616467 100644 --- a/DESCRIPTION +++ b/DESCRIPTION @@ -1,8 +1,8 @@ Package: streamgraph Type: Package Title: streamgraph is an htmlwidget for building streamgraph visualizations -Version: 0.5.1 -Date: 2015-02-15 +Version: 0.7 +Date: 2015-03-12 Author: Bob Rudis (@hrbrmstr) Maintainer: Bob Rudis Description: A streamgraph (or "stream graph") is a type of stacked area graph @@ -21,8 +21,9 @@ Depends: R (>= 3.0.0), htmlwidgets, htmltools, - tidyr Imports: magrittr, - xts + xts, + tidyr, + dplyr VignetteBuilder: knitr diff --git a/NAMESPACE b/NAMESPACE index 1fd2c95..cb03302 100644 --- a/NAMESPACE +++ b/NAMESPACE @@ -1,7 +1,9 @@ -# Generated by roxygen2 (4.1.0.9000): do not edit by hand +# Generated by roxygen2 (4.1.0): do not edit by hand export("%>%") export(renderStreamgraph) +export(sg_add_marker) +export(sg_annotate) export(sg_axis_x) export(sg_axis_y) export(sg_colors) @@ -14,5 +16,9 @@ export(streamgraphOutput) import(htmltools) import(htmlwidgets) import(xts) +importFrom(dplyr,bind_rows) +importFrom(dplyr,left_join) +importFrom(dplyr,mutate) +importFrom(dplyr,select) importFrom(magrittr,"%>%") importFrom(tidyr,expand) diff --git a/R/streamgraph-package.R b/R/streamgraph-package.R index d7258e4..3d14843 100644 --- a/R/streamgraph-package.R +++ b/R/streamgraph-package.R @@ -3,6 +3,7 @@ #' @docType package #' @author Bob Rudis (@@hrbrmstr) #' @import htmlwidgets htmltools xts +#' @importFrom dplyr bind_rows left_join mutate select NULL diff --git a/R/streamgraph.R b/R/streamgraph.R index 3e94821..449e360 100644 --- a/R/streamgraph.R +++ b/R/streamgraph.R @@ -120,6 +120,8 @@ streamgraph <- function(data, params = list( data=data, + markers=NULL, + annotations=NULL, offset=offset, interactive=interactive, interpolate=interpolate, @@ -423,6 +425,67 @@ sg_legend <- function(sg, show=FALSE, label="") { } +#' Add a vertical marker (with optional label) to streamgraph +#' +#' This is useful for marking/labeling notable events along the streams. +#' +#' @param x horizontal position +#' @param label text for the annotation +#' @param stroke_width line width +#' @param stroke line color +#' @param space space (in points) from the marker to place the label +#' @param y vertical position +#' @param color color of the label +#' @param size font size#' @export +#' @param anchor how to justify the label (one of \code{start} [left], +#' \code{middle} [center] or \code{end} [right]) +sg_add_marker <- function(sg, x, label="", stroke_width=0.5, stroke="#7f7f7f", space=5, + y=0, color="#7f7f7f", size=12, anchor="start") { + + if (inherits(x, "Date")) { x <- format(x, "%Y-%m-%d") } + + mark <- data.frame(x=x, y=y, label=label, color=color, stroke_width=stroke_width, stroke=stroke, + space=space, size=size, anchor=anchor, stringsAsFactors=FALSE) + + if (is.null(sg$x$markers)) { + sg$x$markers <- mark + } else { + sg$x$markers <- bind_rows(mark, sg$x$markers) + } + + sg + +} + +#' Add text annotation to streamgraph +#' +#' Use this function to place text at any point on a streamgraph. This +#' is especially useful for non-interactive streamgraphs (i.e. to label +#' a particular stream). +#' +#' @param label text for the annotation +#' @param x horizontal position +#' @param y vertical position +#' @param color color of the label +#' @param size font size +#' @export +sg_annotate <- function(sg, label, x, y, color="black", size=12) { + + if (inherits(x, "Date")) { x <- format(x, "%Y-%m-%d") } + + ann <- data.frame(label=label, x=x, y=y, color=color, size=size, stringsAsFactors=FALSE) + + if (is.null(sg$x$annotations)) { + sg$x$annotations <- ann + } else { + sg$x$annotations <- bind_rows(ann, sg$x$annotations) + } + + sg + +} + + #' Widget output function for use in Shiny #' #' @export diff --git a/README.Rmd b/README.Rmd index dd95d66..f2a0bc7 100644 --- a/README.Rmd +++ b/README.Rmd @@ -1,7 +1,7 @@ --- title: "README" author: "Bob Rudis" -date: March 7, 2015 +date: March 12, 2015 output: md_document: variant: markdown_github @@ -36,6 +36,8 @@ The following functions are implemented: - `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 +- `sg_add_marker` : Annotate streamgraph with vertical line and label +- `sg_annotate` : Annotate streamgraph with a label ### News @@ -51,6 +53,7 @@ The following functions are implemented: - 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. +- Version `0.7` released - New `sg_add_marker` and `sg_annotation` to enable annotation of streamgraphs ### Installation diff --git a/README.md b/README.md index 33f059a..11462cc 100644 --- a/README.md +++ b/README.md @@ -23,6 +23,8 @@ The following functions are implemented: - `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 +- `sg_add_marker` : Annotate streamgraph with vertical line and label +- `sg_annotate` : Annotate streamgraph with a label ### News @@ -38,6 +40,7 @@ The following functions are implemented: - 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. +- Version `0.7` released - New `sg_add_marker` and `sg_annotation` to enable annotation of streamgraphs ### Installation @@ -74,7 +77,6 @@ library(streamgraph) ## Loading required package: htmlwidgets ## Loading required package: htmltools - ## Loading required package: tidyr ``` r library(testthat) @@ -82,7 +84,7 @@ library(testthat) date() ``` - ## [1] "Sat Mar 7 12:45:54 2015" + ## [1] "Thu Mar 12 21:00:31 2015" ``` r test_dir("tests/") diff --git a/inst/htmlwidgets/streamgraph.js b/inst/htmlwidgets/streamgraph.js index 3c39486..a826edd 100644 --- a/inst/htmlwidgets/streamgraph.js +++ b/inst/htmlwidgets/streamgraph.js @@ -1,4 +1,4 @@ -var dbg, dbg2; +var dbg, dbg2, dbg3, dbgs, dbgy, dbgx; HTMLWidgets.widget({ @@ -115,11 +115,16 @@ HTMLWidgets.widget({ .append("g") .attr("transform", "translate(" + margin.left + "," + margin.top + ")"); + dbgs = svg ; + var layers = stack(nest.entries(data)); x.domain(d3.extent(data, function(d) { return d.date; })); y.domain([0, d3.max(data, function(d) { return d.y0 + d.y; })]); + dbgx = x ; + dbgy = y ; + svg.selectAll(".layer") .data(layers) .enter().append("path") @@ -256,9 +261,71 @@ HTMLWidgets.widget({ .append('option') .text(function (d) { return d; }) .attr("value", function (d) { return d; }) - } + } + + if (params.annotations != null) { + + var ann = HTMLWidgets.dataframeToD3(params.annotations) ; + + ann.forEach(function(d) { + if (params.x_scale == "date") { + d.x = format.parse(d.x); + } else { + d.x = +d.x; + } + }); + + svg.selectAll(".annotation") + .data(ann) + .enter().append("text") + .attr("x", function(d) { return(x(d.x)) ; }) + .attr("y", function(d) { return(y(d.y)) ; }) + .attr("fill", function(d) { return(d.color) ; }) + .style("font-size", function(d) { return(d.size+"px") ; }) + .text(function(d) { return(d.label) ;}) + } - }, + if (params.markers != null) { + + var mrk = HTMLWidgets.dataframeToD3(params.markers) ; + + mrk.forEach(function(d) { + if (params.x_scale == "date") { + d.x = format.parse(d.x); + } else { + d.x = +d.x; + } + }); + + dbg3 = mrk ; + svg.selectAll(".marker") + .data(mrk) + .enter().append("line") + .attr("x1", function(d) { return(x(d.x)) ; }) + .attr("x2", function(d) { return(x(d.x)) ; }) + .attr("y1", function(d) { return(y.range()[0]) ; }) + .attr("y2", function(d) { return(y.range()[1]) ; }) + .attr("stroke-width", function(d) { return(d.stroke_width); }) + .attr("stroke", function(d) { return(d.stroke); }) + .attr("stroke-dasharray", "1"); + + svg.selectAll(".markerlab") + .data(mrk) + .enter().append("text") + .attr("x", function(d) { + if (d.anchor=="end") { d.space = -d.space; } + if (d.anchor=="middle") { d.space = 0; } + return(x(d.x)+d.space) ; + }) + .attr("y", function(d) { return(y(d.y)) ; }) + .attr("fill", function(d) { return(d.color) ; }) + .style("font-size", function(d) { return(d.size+"px") ; }) + .style("text-anchor", function(d) { return(d.anchor) ; }) + .text(function(d) { return(d.label) ;}) + + } + + }, resize: function(el, width, height, instance) { if (instance.params) diff --git a/man/renderStreamgraph.Rd b/man/renderStreamgraph.Rd index 758090b..66c1ca9 100644 --- a/man/renderStreamgraph.Rd +++ b/man/renderStreamgraph.Rd @@ -1,4 +1,4 @@ -% Generated by roxygen2 (4.1.0.9000): do not edit by hand +% Generated by roxygen2 (4.1.0): do not edit by hand % Please edit documentation in R/streamgraph.R \name{renderStreamgraph} \alias{renderStreamgraph} diff --git a/man/sg_add_marker.Rd b/man/sg_add_marker.Rd new file mode 100644 index 0000000..dcf7559 --- /dev/null +++ b/man/sg_add_marker.Rd @@ -0,0 +1,33 @@ +% Generated by roxygen2 (4.1.0): do not edit by hand +% Please edit documentation in R/streamgraph.R +\name{sg_add_marker} +\alias{sg_add_marker} +\title{Add a vertical marker (with optional label) to streamgraph} +\usage{ +sg_add_marker(sg, x, label = "", stroke_width = 0.5, stroke = "#7f7f7f", + space = 5, y = 0, color = "#7f7f7f", size = 12, anchor = "start") +} +\arguments{ +\item{x}{horizontal position} + +\item{label}{text for the annotation} + +\item{stroke_width}{line width} + +\item{stroke}{line color} + +\item{space}{space (in points) from the marker to place the label} + +\item{y}{vertical position} + +\item{color}{color of the label} + +\item{size}{font size#'} + +\item{anchor}{how to justify the label (one of \code{start} [left], +\code{middle} [center] or \code{end} [right])} +} +\description{ +This is useful for marking/labeling notable events along the streams. +} + diff --git a/man/sg_annotate.Rd b/man/sg_annotate.Rd new file mode 100644 index 0000000..57d7733 --- /dev/null +++ b/man/sg_annotate.Rd @@ -0,0 +1,25 @@ +% Generated by roxygen2 (4.1.0): do not edit by hand +% Please edit documentation in R/streamgraph.R +\name{sg_annotate} +\alias{sg_annotate} +\title{Add text annotation to streamgraph} +\usage{ +sg_annotate(sg, label, x, y, color = "black", size = 12) +} +\arguments{ +\item{label}{text for the annotation} + +\item{x}{horizontal position} + +\item{y}{vertical position} + +\item{color}{color of the label} + +\item{size}{font size} +} +\description{ +Use this function to place text at any point on a streamgraph. This +is especially useful for non-interactive streamgraphs (i.e. to label +a particular stream). +} + diff --git a/man/sg_axis_x.Rd b/man/sg_axis_x.Rd index 8f8dbfc..9ec9bdc 100644 --- a/man/sg_axis_x.Rd +++ b/man/sg_axis_x.Rd @@ -1,4 +1,4 @@ -% Generated by roxygen2 (4.1.0.9000): do not edit by hand +% Generated by roxygen2 (4.1.0): do not edit by hand % Please edit documentation in R/streamgraph.R \name{sg_axis_x} \alias{sg_axis_x} diff --git a/man/sg_axis_y.Rd b/man/sg_axis_y.Rd index dc75cf9..facf38e 100644 --- a/man/sg_axis_y.Rd +++ b/man/sg_axis_y.Rd @@ -1,4 +1,4 @@ -% Generated by roxygen2 (4.1.0.9000): do not edit by hand +% Generated by roxygen2 (4.1.0): do not edit by hand % Please edit documentation in R/streamgraph.R \name{sg_axis_y} \alias{sg_axis_y} diff --git a/man/sg_colors.Rd b/man/sg_colors.Rd index 2478e9a..83e14a9 100644 --- a/man/sg_colors.Rd +++ b/man/sg_colors.Rd @@ -1,4 +1,4 @@ -% Generated by roxygen2 (4.1.0.9000): do not edit by hand +% Generated by roxygen2 (4.1.0): do not edit by hand % Please edit documentation in R/streamgraph.R \name{sg_colors} \alias{sg_colors} diff --git a/man/sg_fill_brewer.Rd b/man/sg_fill_brewer.Rd index 1638a89..f12c5df 100644 --- a/man/sg_fill_brewer.Rd +++ b/man/sg_fill_brewer.Rd @@ -1,4 +1,4 @@ -% Generated by roxygen2 (4.1.0.9000): do not edit by hand +% Generated by roxygen2 (4.1.0): do not edit by hand % Please edit documentation in R/streamgraph.R \name{sg_fill_brewer} \alias{sg_fill_brewer} diff --git a/man/sg_fill_manual.Rd b/man/sg_fill_manual.Rd index 72d33a4..f67b2e6 100644 --- a/man/sg_fill_manual.Rd +++ b/man/sg_fill_manual.Rd @@ -1,4 +1,4 @@ -% Generated by roxygen2 (4.1.0.9000): do not edit by hand +% Generated by roxygen2 (4.1.0): do not edit by hand % Please edit documentation in R/streamgraph.R \name{sg_fill_manual} \alias{sg_fill_manual} diff --git a/man/sg_fill_tableau.Rd b/man/sg_fill_tableau.Rd index b3ad8b3..1036a82 100644 --- a/man/sg_fill_tableau.Rd +++ b/man/sg_fill_tableau.Rd @@ -1,4 +1,4 @@ -% Generated by roxygen2 (4.1.0.9000): do not edit by hand +% Generated by roxygen2 (4.1.0): do not edit by hand % Please edit documentation in R/streamgraph.R \name{sg_fill_tableau} \alias{sg_fill_tableau} diff --git a/man/sg_legend.Rd b/man/sg_legend.Rd index ba49bcc..4507e86 100644 --- a/man/sg_legend.Rd +++ b/man/sg_legend.Rd @@ -1,4 +1,4 @@ -% Generated by roxygen2 (4.1.0.9000): do not edit by hand +% Generated by roxygen2 (4.1.0): do not edit by hand % Please edit documentation in R/streamgraph.R \name{sg_legend} \alias{sg_legend} diff --git a/man/streamgraph-exports.Rd b/man/streamgraph-exports.Rd index fd4ef16..a0415ea 100644 --- a/man/streamgraph-exports.Rd +++ b/man/streamgraph-exports.Rd @@ -1,4 +1,4 @@ -% Generated by roxygen2 (4.1.0.9000): do not edit by hand +% Generated by roxygen2 (4.1.0): do not edit by hand % Please edit documentation in R/streamgraph-package.R \name{streamgraph-exports} \alias{\%>\%} diff --git a/man/streamgraph-package.Rd b/man/streamgraph-package.Rd index 040a4e9..0f3d5d3 100644 --- a/man/streamgraph-package.Rd +++ b/man/streamgraph-package.Rd @@ -1,4 +1,4 @@ -% Generated by roxygen2 (4.1.0.9000): do not edit by hand +% Generated by roxygen2 (4.1.0): do not edit by hand % Please edit documentation in R/streamgraph-package.R \docType{package} \name{streamgraph-package} diff --git a/man/streamgraph.Rd b/man/streamgraph.Rd index 6345bb8..5839448 100644 --- a/man/streamgraph.Rd +++ b/man/streamgraph.Rd @@ -1,4 +1,4 @@ -% Generated by roxygen2 (4.1.0.9000): do not edit by hand +% Generated by roxygen2 (4.1.0): do not edit by hand % Please edit documentation in R/streamgraph.R \name{streamgraph} \alias{streamgraph} diff --git a/man/streamgraphOutput.Rd b/man/streamgraphOutput.Rd index e5d379e..df35622 100644 --- a/man/streamgraphOutput.Rd +++ b/man/streamgraphOutput.Rd @@ -1,4 +1,4 @@ -% Generated by roxygen2 (4.1.0.9000): do not edit by hand +% Generated by roxygen2 (4.1.0): do not edit by hand % Please edit documentation in R/streamgraph.R \name{streamgraphOutput} \alias{streamgraphOutput} diff --git a/tests/testthat/sg.R b/tests/testthat/sg.R index 84278c1..a528d40 100644 --- a/tests/testthat/sg.R +++ b/tests/testthat/sg.R @@ -88,7 +88,17 @@ dat <- read.table(text="week variable value 44 rev1 357.504 44 rev2 466.560", header=TRUE) -dat %>% streamgraph("variable","value","week", scale="continuous") %>% sg_axis_x(tick_format="d") +dat %>% + streamgraph("variable","value","week", scale="continuous") %>% + sg_axis_x(tick_format="d") %>% + sg_fill_tableau() %>% +# sg_annotate(label="annotation", x=40.05, y=200, color="white", size=16) %>% +# sg_annotate(label="moar annotation", x=41, y=1500, color="black", size=24) %>% +# sg_annotate(label="last one", x=42, y=900, color="white", size=18) %>% + sg_add_marker(x=41, y=10, label="Hello There", stroke="#000000", color="#7f7f7f", size=16) %>% + sg_add_marker(x=42, y=10, label="Hello There", stroke="#000000", color="#7f7f7f", size=16) %>% + sg_add_marker(x=43, y=10, label="Hello There", stroke="#000000", color="#7f7f7f", size=16) +